Trouver le bon répertoire tmp sur plusieurs plates-formes

46

J'ai un script qui doit créer des fichiers temporaires pour son travail et nettoyer après lui-même. Ma question concerne la recherche du bon répertoire de base pour les fichiers temporaires.

Le script doit fonctionner sur plusieurs plates-formes: Git Bash (Windows), Solaris, Linux, OSX. Sur chaque plate-forme, le répertoire temporaire préféré est exprimé différemment:

  • Windows: %TMP%(et éventuellement %TEMP%)
  • OSX: $TMPDIR
  • Linux, UNIX: censé être $TMPDIRmais semble être non défini sur plusieurs systèmes, j'ai essayé

Donc, dans mon script, j'ai ajouté ce passe-partout:

if test -d "$TMPDIR"; then
    :
elif test -d "$TMP"; then
    TMPDIR=$TMP
elif test -d /var/tmp; then
    TMPDIR=/var/tmp
else
    TMPDIR=/tmp
fi

Cela semble trop fastidieux. Y a-t-il un meilleur moyen?

Arrêtez de nuire à Monica
la source
6
Juste utiliser ${TMPDIR-/tmp}sur les goûts Unix. TMPDIRExiste-t-il (de la part du système ou de l'administrateur ou de l'utilisateur) de vous dire quand ne pas utiliser /tmples fichiers temporaires?
Stéphane Chazelas

Réponses:

72

Un moyen légèrement plus portable de gérer les fichiers temporaires consiste à utiliser mktemp. Cela créera des fichiers temporaires et vous renverra les chemins. Par exemple:

$ mktemp
/tmp/tmp.zVNygt4o7P
$ ls /tmp/tmp.zVNygt4o7P
/tmp/tmp.zVNygt4o7P

Vous pouvez l'utiliser facilement dans un script:

tmpfile=$(mktemp)
echo "Some temp. data..." > $tmpfile
rm $tmpfile

En lisant la page de manuel, vous devriez pouvoir définir les options en fonction de vos besoins. Par exemple:

  • -d crée un répertoire au lieu d'un fichier.
  • -u génère un nom, mais ne crée rien.

En utilisant -uvous pourriez récupérer le répertoire temporaire assez facilement avec ...

$ tmpdir=$(dirname $(mktemp -u))

Plus d'informations sur mktempsont disponibles ici .

Modification concernant Mac OS X: Je n’ai jamais utilisé de système Mac OSX, mais selon un commentaire de Tyilo ci-dessous, il semble que celui-ci mktempnécessite que vous fournissiez un modèle (qui est un argument optionnel sous Linux). Citant:

Le modèle peut être n'importe quel nom de fichier avec un certain nombre de "X", par exemple /tmp/temp.XXXX. Les "X" suivants sont remplacés par le numéro de processus actuel et / ou une combinaison de lettres unique. Le nombre de noms de fichiers uniques que mktemp peut renvoyer dépend du nombre de "X" fournis; Avec six "X", mktemp sélectionnera l'un des 56800235584 (62 ** 6) noms de fichiers possibles.

La page de manuel indique également que cette implémentation est inspirée de la page de manuel OpenBSD mktemp. Une divergence similaire pourrait donc être observée par les utilisateurs OpenBSD et FreeBSD (voir la section Historique ).

Maintenant, comme vous l'avez probablement remarqué, cela nécessite que vous spécifiiez un chemin d'accès complet au fichier, y compris le répertoire temporaire que vous recherchez dans votre question. Ce petit problème peut être traité à l'aide du -tcommutateur. Bien que cette option semble nécessiter un argument ( prefix), il semblerait que mktempcela dépende $TMPDIRlorsque cela est nécessaire.

Globalement, vous devriez pouvoir obtenir le même résultat que ci-dessus en utilisant ...

$ tmpdir=$(dirname $(mktemp tmp.XXXXXXXXXX -ut))

Toute réaction des utilisateurs de Mac OS X serait grandement appréciée, car je suis incapable de tester cette solution moi-même.

John WH Smith
la source
Le PO a abordé cette question dans un commentaire maintenant supprimé. Je crains de ne pouvoir fournir une réponse aux systèmes nécessitant gitbashune interface shell, d’où mon "légèrement". En fait, je serais incapable de dire où les fichiers temporaires sont stockés sur un système Windows ...
John WH Smith
1
idem ça. Certains sont fous c:\User\Name\..............\stuff. Et il y en a probablement 100. Pourtant, certaines distributions Linux approchent du même niveau de folie en /var. J'étais juste curieux. Cela m’a semblé étrange: c’est mon expérience qui fait que la frustration est très portable et que la commodité l’est moins. Très bonne réponse quand même.
mikeserv
1
Il y a environ un an, j'ai écrit un script Bash pour manipuler les fichiers du point de restauration Windows qui fonctionne de Win2K à WinXP (les versions ultérieures gèrent ce genre de choses différemment). Mon script utilise WINDOWS/Tempou Windows/Tempcomme répertoire par défaut pour ses fichiers temporaires; Ce répertoire existe également sur les machines Windows 7. Mais mon script permet à l'utilisateur de fournir un autre répertoire temporaire sur la ligne de commande.
PM 2Ring
Cela ne fonctionnerait pas sous OS X, car vous devez fournir un modèle mktemp.
Tyilo
1
Depuis El Capitan, mktempça fonctionne: simple mktemprenvoie un fichier et mktemp -dun répertoire; aucun modèle requis. Le manuel n'est pas mis à jour cependant.
Franklin Yu
9

Si vous cherchez la même chose en moins de lignes ...

for TMPDIR in "$TMPDIR" "$TMP" /var/tmp /tmp
do
    test -d "$TMPDIR" && break
done

Vous pouvez écrire ceci dans un.

Frostschutz
la source
Vous devriez probablement aussi vérifier si c'est accessible en écriture.
frostschutz
@janos: Et si tout échoue, demandez à l'utilisateur de fournir un chemin pour les fichiers temporaires ou autorisez-le à en spécifier un sur la ligne de commande.
PM 2Ring
6

Vous pourriez faire:

: "${TMPDIR:=${TMP:-$(CDPATH=/var:/; cd -P tmp)}}"
cd -- "${TMPDIR:?NO TEMP DIRECTORY FOUND!}" || exit

Le shell devrait soit trouver un répertoire exécutable dans l’une des 4 alternatives, soit quitter avec une erreur significative. Néanmoins, POSIX définit la $TMPDIRvariable (pour les systèmes XCU) :

TMPDIR Cette variable doit représenter le chemin d'un répertoire mis à la disposition des programmes ayant besoin d'un emplacement pour créer des fichiers temporaires.

Il faut aussi le /tmpchemin.

Mikeserv
la source
1
C’est la seule bonne réponse ici, OMI. Je ne sais pas ce qu'il fait assis en bas sans vote ...
Graeme
2
@Graeme: peut-être parce que c'est totalement illisible?
SSC
Oui, cette réponse est un gâchis, elle semble être sur une piste utile, mais ce que l'extrait de code tente de faire n'est pas claire, la première ligne est un commentaire et la seconde l'un est une erreur (en bash, en tout cas). Pourrait utiliser du travail.
Don Hatch
Oh, je vois, la première version de la réponse était plus claire (une erreur sur la deuxième ligne si vous essayez réellement de l'exécuter) ... et ensuite une série de modifications ont complètement détruit l'échantillon de code, ce qui est donc absurde. Pourrait utiliser une autre passe ou deux :-)
Don Hatch