Correzione o alternativa per mktemp in OS X


73

Sto guardando uno script bash che qualcun altro ha scritto che usa mktemp:

TEMP=`mktemp --directory`

Tuttavia, questa linea non funziona sulla mia macchina (OS X 10.6).

Come risolverei questa linea in modo che sia compatibile con la piattaforma cross-un * x-like? EDIT: sarebbe sufficiente anche un comando alternativo.

Risposte:


109

Quello che segue è quello che ho finito per creare in modo affidabile una directory temporanea che funziona sia su Linux che su Darwin (tutte le versioni precedenti a Mac OS X 10.11), senza hardcoding $TMPDIRo /tmp:

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

Sfondo:

Il comando GNU mktemp non richiede argomenti. Plain mktempfunzionerà e crea un file temporaneo nella directory temporanea del sistema.

Plain mktemp -dcreerà una directory anziché un file, che è quello che vorresti usare su Linux.

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

Per impostazione predefinita, GNU mktemp usa il modello tmp.XXXXXXXXXXper il nome della sottodirectory (o del file). Per personalizzare questo modello, è -tpossibile utilizzare l' opzione.

Mktemp di OSX non ha un modello predefinito e richiede un modello da specificare. Sfortunatamente, dove GNU mktemp accetta il modello come -topzione, su OSX questo viene passato come argomento posizionale. Invece, mktemp di OSX ha -tun'opzione che significa qualcos'altro. L' -topzione su OSX è documentata come "prefisso" per il modello. Viene espanso in {prefix}.XXXXXXXX, quindi aggiunge automaticamente le X (ad es. mktemp -d -t examplePotrebbe creare example.zEJZWCTQnella directory temp).

Sono stato sorpreso di scoprire che in molti ambienti Linux non$TMPDIR è impostato di default. Molti programmi CLI lo supportano quando sono impostati, ma necessitano ancora di un valore predefinito per . Ciò significa che passare a mktemp o mkdir è pericoloso perché può produrre nella directory principale del disco locale (a causa del fatto che $ TMPDIR non viene impostato e diventa una stringa vuota)./tmp$TMPDIR/example.XXXXXXXX/example.XXXXXXXX

Su OSX, $TMPDIRè sempre impostato e (almeno nella shell predefinita) non è impostato su /tmp(che è un collegamento simbolico a /private/tmp) ma su /var/folders/dx/*****_*************/T. Quindi, qualunque cosa facciamo per OSX, dovrebbe rispettare quel comportamento predefinito.

In conclusione, il seguente è quello che ho finito per usare a creare in modo affidabile una directory temporanea che funziona sia su Linux e Darwin (Mac OS X), senza hardcoding sia $TMPDIRo /tmp:

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

La prima parte è per Linux. Questo comando fallirà su Darwin (Mac OS X) con il codice di stato dell'errore che 1risponde con "utilizzo: ...". Ecco perché ignoriamo stderr e invece eseguiamo la variante per Mac. Il mytmpdirprefisso viene utilizzato solo su Mac (dove è necessario impostare tale opzione).


12
Veramente cool. A volte il comportamento diverso di OS X è fastidioso.
therealmarv,

6
@therealmarv Preferirei sempre dire.
Nikita Volkov,

10
Ho appena eseguito mktemp -dsu OS X 10.11.5 El Capitan, e ha funzionato come previsto file $(mktemp -d):: /var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders,

2
Sì. Sono rimasto sorpreso dal fatto che questo Just Worked ™.
Heath Borders,

1
Inoltre, se si esegue mktemp -d -t 'mytmpdir'su Linux (testato con mktempda coreutils 8.26), funziona come previsto.

15

Devi fornire un modello. mktemp -d /tmp/foo.XXXXdovrebbe funzionare. Non ho mai visto --directory. Il --suggerisce che è un'estensione GNU.


6
Se vuoi usarlo $TMPDIRquando disponibile, fallo mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX. Funziona su bash su Mac e su Debian, quindi sembra portatile.
Tom Anderson,

9

Cambia --directoryin -d. Il primo è un GNU-ism, ma mktempsupporta anche GNU di coreutils -d. In mktempOS X è lo stesso di BSD, quindi -ddovrebbe essere abbastanza portatile tra i sistemi che effettivamente distribuiscono un mktempprogramma.


Ho appena provato mktemp -de non funziona neanche.
mindeavour.

1
Kyle ha la risposta completa. L' mktempOS su X richiede un modello. Lo script che stai utilizzando presuppone le convenzioni GNU, che utilizza un modello predefinito se non ne viene fornito nessuno.
James Sneeringer,

Il problema è che unix prevede XXXXXdi essere fornito nel modello in cui OS X non è sicuro se esiste un flag di modello compatibile?
user3467349

2
mktempsu OS X 10.11.5 El Capitan lavora per me 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")"
  • mktempper BSD (incluso OSX ) richiede un modello, ma consente un numero qualsiasi di Xs nel modello.
  • (GNU) mktempper Linux non richiede un modello, tuttavia, se viene specificato un modello, il numero di Xs deve essere 6.

Nota che -tè deprecato per GNUmktemp , quindi sarebbe un codice più a prova di futuro

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.