Fix oder Alternative für mktemp in OS X

73

Ich schaue mir ein Bash-Skript an, das jemand anderes geschrieben hat und das verwendet mktemp:

TEMP=`mktemp --directory`

Diese Leitung funktioniert jedoch auf meinem Computer nicht (OS X 10.6).

Wie kann ich diese Leitung so reparieren, dass sie plattformübergreifend kompatibel ist? EDIT: Ein alternativer Befehl wäre auch ausreichend.

mindeavour.
quelle

Antworten:

109

Folgendes habe ich letztendlich verwendet, um zuverlässig ein temporäres Verzeichnis zu erstellen, das sowohl unter Linux als auch unter Darwin (alle Versionen vor Mac OS X 10.11) ohne Hardcodierung $TMPDIRoder /tmp:

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

Hintergrund:

Der Befehl GNU mktemp benötigt keine Argumente. Plain mktempfunktioniert und erstellt eine temporäre Datei im temporären Verzeichnis des Systems.

Plain mktemp -derstellt ein Verzeichnis anstelle einer Datei, die Sie unter Linux verwenden möchten.

(gnu-coreutils)$ man mktemp
> ..
> If DIR is not specified, uses $TMPDIR if set, else /tmp.
> ..

Standardmäßig verwendet GNU mktemp die Vorlage tmp.XXXXXXXXXXfür den Namen des Unterverzeichnisses (oder der Datei). Zum Anpassen dieser Vorlage kann die -tOption verwendet werden.

OSXs mktemp hat keine Standardvorlage und erfordert die Angabe einer Vorlage. Wenn GNU mktemp die Vorlage als -tOption verwendet, wird dies unter OSX leider als Positionsargument übergeben. Stattdessen hat OSXs mktemp eine -tOption, die etwas anderes bedeutet. Die -tOption unter OSX ist als "Präfix" für die Vorlage dokumentiert. Es wird auf erweitert {prefix}.XXXXXXXX, so dass es die Xs automatisch hinzufügt (z. B. im temporären Verzeichnis mktemp -d -t exampleerstellen example.zEJZWCTQ).

Ich war überrascht , dass in Umgebungen viele Linux zu finden $TMPDIRist nicht standardmäßig aktiviert. Viele CLI-Programme unterstützen diese Einstellung, benötigen jedoch weiterhin eine Standardeinstellung für /tmp. Dies bedeutet, dass die Übergabe $TMPDIR/example.XXXXXXXXan mktemp oder mkdir gefährlich ist, da sie möglicherweise /example.XXXXXXXXim Stammverzeichnis der lokalen Festplatte erstellt wird (da $ TMPDIR nicht gesetzt ist und eine leere Zeichenfolge wird).

Unter OSX $TMPDIRist immer gesetzt und (zumindest in der Standardshell) nicht gesetzt /tmp(was ein Symlink zu ist /private/tmp), sondern zu /var/folders/dx/*****_*************/T. Was auch immer wir für OSX tun, sollte dieses Standardverhalten berücksichtigen.

Abschließend habe ich Folgendes verwendet, um zuverlässig ein temporäres Verzeichnis zu erstellen, das sowohl unter Linux als auch unter Darwin (Mac OS X) funktioniert, ohne entweder eine Hardcodierung $TMPDIRoder /tmp:

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

Der erste Teil ist für Linux. Dieser Befehl schlägt unter Darwin (Mac OS X) mit dem Fehlerstatuscode 1"usage: ..." fehl . Deshalb ignorieren wir stderr und führen stattdessen die Mac-Variante aus. Das mytmpdirPräfix wird nur auf dem Mac verwendet (wo diese Option festgelegt werden muss).

Timo Tijhof
quelle
12
Wirklich cool. Manchmal ist ein anderes Verhalten von OS X ärgerlich.
Therealmarv
6
@therealmarv Ich würde lieber immer sagen.
Nikita Volkov
10
Ich lief gerade mktemp -dauf OS X 10.11.5 El Capitan, und es funktionierte wie erwartet file $(mktemp -d): /var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders
2
Ja. Ich war überrascht, wie Sie waren, dass dies Just Worked ™.
Heath Borders
1
Auch wenn Sie mktemp -d -t 'mytmpdir'unter Linux laufen (getestet mit mktempfrom coreutils 8.26), funktioniert es wie erwartet.
15

Sie müssen eine Vorlage angeben. mktemp -d /tmp/foo.XXXXsollte arbeiten. Ich habe noch nie gesehen --directory. Das --deutet darauf hin, dass es sich um eine GNU-Erweiterung handelt.

Kyle Jones
quelle
6
Wenn Sie verwenden möchten, $TMPDIRwenn verfügbar, tun Sie dies mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX. Das funktioniert in Bash auf dem Mac und Dash auf Debian, also scheint es portabel zu sein.
Tom Anderson
9

Wechseln Sie --directoryzu -d. Ersteres ist ein GNU-Ismus, aber GNU mktempvon coreutils unterstützt auch -d. Das mktempin OS X ist das gleiche wie von BSD, -dsollte also unter Systemen, die tatsächlich ein mktempProgramm liefern, ziemlich portabel sein .

James Sneeringer
quelle
Ich habe es gerade versucht mktemp -d, und es funktioniert auch nicht.
Bemühen Sie sich.
1
Kyle hat die vollständige Antwort. Für mktempOS X ist eine Vorlage erforderlich. Das Skript, das Sie verwenden, setzt GNU-Konventionen voraus, die eine Standardvorlage verwenden, wenn keine angegeben ist.
James Sneeringer
Das Problem ist, dass Unix erwartet XXXXX, in der Vorlage geliefert zu werden, wo als OS X nicht sicher ist, ob es ein kompatibles Vorlagenflag gibt?
user3467349
2
mktempUnter OS X 10.11.5 funktioniert El Capitan für mich file $(mktemp -d):/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders
4
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktempFür BSD (einschließlich OSX ) ist eine Vorlage erforderlich, die jedoch eine beliebige Anzahl von Xs in der Vorlage zulässt .
  • (GNU) mktempfür Linux erfordert keine Vorlage. Wenn jedoch eine Vorlage angegeben ist, muss die Anzahl der Xs 6 betragen.

Beachten Sie, dass dies -tfür GNUmktemp veraltet ist , so dass ein zukunftssicherer Code wäre

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
go2null
quelle