Come creare una directory temporanea?


229

Uso per creare un tempfile, eliminarlo e ricrearlo come una directory:

tmpnam=`tempfile`
rm -f $tmpnam
mkdir "$tmpnam"

Il problema è che un altro processo può avere lo stesso nome X, se esegue accidentalmente tempfile dopo un processo rm -f Xe poco prima mkdir X.

Risposte:


341

Usa mktemp -d. Crea una directory temporanea con un nome casuale e si assicura che il file non esista già. Tuttavia, è necessario ricordare di eliminare la directory dopo averla utilizzata.


25
Ho dovuto usaremktemp -d -t <prefix>
Heath Borders il

17
Questa è una cosa OS X vs Linux. Vedi questa domanda per una versione che funziona su entrambi: unix.stackexchange.com/questions/30091/…
jwhitlock

2
Inoltre, vedi la risposta di seguito riportata da Ortwin, poiché ciò assicura che venga eseguita anche la pulizia.
Mathiasdm,

5
Perché dici "Devi ricordare di eliminare la directory dopo averla usata però"? Questo non vanifica lo scopo di usare una directory temporanea?
MK Safi,

73

Per una soluzione più solida utilizzo qualcosa di simile al seguente. In questo modo la directory temporanea verrà sempre eliminata dopo la chiusura dello script.

La funzione di pulizia viene eseguita sul EXITsegnale. Ciò garantisce che la funzione di pulizia sia sempre chiamata, anche se lo script si interrompe da qualche parte.

#!/bin/bash    

# the directory of the script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# the temp directory used, within $DIR
# omit the -p parameter to create a temporal directory in the default location
WORK_DIR=`mktemp -d -p "$DIR"`

# check if tmp dir was created
if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then
  echo "Could not create temp dir"
  exit 1
fi

# deletes the temp directory
function cleanup {      
  rm -rf "$WORK_DIR"
  echo "Deleted temp working directory $WORK_DIR"
}

# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT

# implementation of script starts here
...

Elenco di script bash da qui .

Bash trappole .


26
Attenzione a FreeBSD! mktemp su FreeBSD non ha l'opzione -p, e cleanupsarà rm -rf la directory corrente!
madfriend

1
Buon punto, aggiornato lo script per verificare se è possibile creare la directory temporanea.
Ortwin Angermeier,

1
@madfriend davvero? se mktempfallisce, WORK_DIRsarà vuoto, il che significa che il comando sarebbe rm -rfsenza argomenti. Non uso FreeBSD ma sarei piuttosto sorpreso se rm -rffosse equivalente arm -rf .
jbg

@jbg sì, mi sembra strano anche adesso - non dovrebbe essere un grosso problema. Avrei potuto modificare una vecchia versione di questo script in modo che un percorso alla directory temporanea fosse calcolato relativamente alla directory corrente, con conseguente <s> estinzione dell'umanità </s> rimozione della directory corrente.
pazzo

1
Per renderlo migliore, è possibile evitare una directory vuota o almeno contenere il problema all'interno di una directory utilizzando una soluzione in cui si esegue: 1. TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/')e quindi 2 rmdir /tmp/git/"${TMPWORKDIR}".. Se la variabile è vuota ora, si tornerà a /tmp/git/non all'intero sistema. Considera qualcosa di simile nella risposta e sarò felice di essere d'accordo. ;)
Dott. Beco

64

Il mio one-liner preferito per questo è

cd $(mktemp -d)

10
e rm $(pwd)? : P
Arran Cudbard-Bell,

19
utile anche: pushd $(mktemp -d)...popd
Ponkadoodle il

4
@ ArranCudbard-Bell dovrebbe essererm -r $(pwd)
salvadanaio

31
@piggybox Francamente, sarei molto cauto nell'usarlo rm -r $(pwd). Considerare la possibilità che la creazione temporanea di directory non riesca per qualsiasi motivo (forse il filesystem / tmp è pieno o è stato rimontato in lettura solo a causa di un errore?); quindi cd $(mktemp -d)valuterà a cdquali modifiche alla home directory dell'utente, che verranno successivamente eliminate.
Jules

1
Potrebbe essere sicuro conif pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi
AndreyS Scherbakov il

9

Il frammento seguente creerà in modo sicuro una directory temporanea ( -d) e memorizzerà il suo nome nel fileTMPDIR . (Un esempio di utilizzo diTMPDIR variabile viene mostrato più avanti nel codice in cui viene utilizzato per archiviare i file originali che potrebbero essere modificati.)

La prima trapriga esegue il exit 1comando quando viene ricevuto uno qualsiasi dei segnali specificati . La seconda trapriga rimuove (pulisce) l' $TMPDIRuscita del programma (sia normale che anormale). Inizializziamo queste trap dopo aver verificato che è mkdir -driuscito a evitare di eseguire accidentalmente la trap di uscita con $TMPDIRuno stato sconosciuto.

#!/bin/bash

# Create a temporary directory and store its name in a variable ...
TMPDIR=$(mktemp -d)

# Bail out if the temp directory wasn't created successfully.
if [ ! -e $TMPDIR ]; then
    >&2 echo "Failed to create temp directory"
    exit 1
fi

# Make sure it gets removed even if the script exits abnormally.
trap "exit 1"           HUP INT PIPE QUIT TERM
trap 'rm -rf "$TMPDIR"' EXIT

# Example use of TMPDIR:
for f in *.csv; do
    cp "$f" "$TMPDIR"
    # remove duplicate lines but keep order
    perl -ne 'print if ++$k{$_}==1' "$TMPDIR/$f" > "$f"
done

1
Sebbene questa sia una soluzione interessante per la gestione degli errori, sarebbe utile una spiegazione un po 'più dei vantaggi e delle possibili carenze.
Murphy,

1.) -dcontrolla le directory. 2.) La terminazione è già predefinita per quei segnali.
ceving il
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.