web-dev-qa-db-fra.com

Correctif ou alternative pour mktemp sous OS X

Je regarde un script bash écrit par quelqu'un d'autre qui utilise mktemp:

TEMP=`mktemp --directory`

Cependant, cette ligne ne fonctionne pas sur ma machine (OS X 10.6).

Comment pourrais-je corriger cette ligne afin qu'elle soit compatible avec la plateforme cross-un * x-like? EDIT: Une commande alternative serait également suffisante.

78
soundly_typed

Voici ce que j'ai fini par utiliser pour créer de manière fiable un répertoire temporaire qui fonctionne à la fois sur Linux et Darwin (toutes les versions avant Mac OS X 10.11), sans codage en dur $TMPDIR Ou /tmp:

mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')

Contexte:

La commande GNU mktemp ne nécessite aucun argument. Plain mktemp fonctionnera et créera un fichier temporaire dans le répertoire temporaire du système.

Plain mktemp -d Créera un répertoire au lieu d'un fichier, ce que vous voudriez utiliser sous Linux.

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

Par défaut, GNU mktemp utilise le modèle tmp.XXXXXXXXXX Pour le nom du sous-répertoire (ou fichier). Pour personnaliser ce modèle, l'option -t Peut être utilisé.

Mktemp d'OSX n'a ​​pas de modèle par défaut et nécessite qu'un modèle soit spécifié. Malheureusement, où GNU mktemp prend le modèle comme option -t, Sous OSX, cela est passé comme argument positionnel. Au lieu de cela, mktemp d'OSX a une option -t Qui signifie autre chose. L'option -t sur OSX est documentée comme un "préfixe" pour le modèle. Elle est étendue à {prefix}.XXXXXXXX, donc elle y ajoute automatiquement les X (par exemple mktemp -d -t example pourrait créer example.zEJZWCTQ dans le répertoire temporaire).

J'ai été surpris de constater que dans de nombreux environnements Linux, $TMPDIR Est pas défini par défaut. De nombreux programmes CLI le prennent en charge une fois défini, mais nécessitent toujours une valeur par défaut pour /tmp. Cela signifie que passer $TMPDIR/example.XXXXXXXX À mktemp ou mkdir est dangereux car il peut produire /example.XXXXXXXX Dans le répertoire racine du disque local (car $ TMPDIR n'est pas défini et devient un chaîne vide).

Sous OSX, $TMPDIR Est toujours défini et (au moins dans le shell par défaut) il n'est pas défini sur /tmp (Qui est un lien symbolique vers /private/tmp) Mais sur /var/folders/dx/*****_*************/T. Donc, quoi que nous fassions pour OSX, devrait respecter ce comportement par défaut.

En conclusion, voici ce que j'ai fini par utiliser pour créer de manière fiable un répertoire temporaire qui fonctionne à la fois sur Linux et Darwin (Mac OS X), sans codage en dur ni $TMPDIR Ni /tmp:

mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')

La première partie est pour Linux. Cette commande échouera sur Darwin (Mac OS X) avec le code d'état d'erreur 1 Répondant avec "usage: ...". C'est pourquoi nous ignorons stderr et exécutons plutôt la variante Mac. Le préfixe mytmpdir n'est utilisé que sur Mac (où cette option doit être définie).

117
Timo Tijhof

Vous devez fournir un modèle. mktemp -d /tmp/foo.XXXX devrait marcher. Je n'ai jamais vu --directory. Le -- suggère qu'il s'agit d'une extension GNU.

15
Kyle Jones

Changement --directory à -d. Le premier est un GNU-isme, mais GNU mktemp de coreutils prend également en charge -d. mktemp dans OS X est le même que pour BSD, donc -d devrait être assez portable parmi les systèmes qui embarquent réellement un programme mktemp.

9
James Sneeringer
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktemp pour BSD (y compris OSX ) nécessite un modèle, mais il autorise n'importe quel nombre de Xs dans le modèle.
  • (GNU) mktemp pour Linux ne nécessite pas de modèle, cependant, si un modèle est spécifié, le nombre de Xs doit être 6.

Notez que -t est déconseillé pour GNU mktemp , donc un code plus évolutif serait

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