Wie erstelle ich ein temporäres Verzeichnis?


228

Ich erstelle ein tempfile, lösche es und erstelle es als Verzeichnis neu:

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

Das Problem ist, dass ein anderer Prozess möglicherweise denselben Namen erhält X, wenn er versehentlich nach einem Prozess rm -f Xund kurz zuvor tempfile ausführt mkdir X.

Antworten:


339

Verwenden Sie mktemp -d. Es erstellt ein temporäres Verzeichnis mit einem zufälligen Namen und stellt sicher, dass die Datei noch nicht vorhanden ist. Sie müssen jedoch daran denken, das Verzeichnis nach der Verwendung zu löschen.


25
Ich musstemktemp -d -t <prefix>
Heath Borders

17
Dies ist eine Sache von OS X gegen Linux. Siehe diese Frage für eine Version, die auf beiden funktioniert: unix.stackexchange.com/questions/30091/…
jwhitlock

2
Siehe auch die Antwort von Ortwin unten, da dies sicherstellt, dass auch die Bereinigung durchgeführt wird.
Mathiasdm

5
Warum sagen Sie "Sie müssen daran denken, das Verzeichnis zu löschen, nachdem Sie es verwendet haben."? Besiegt das nicht den Zweck der Verwendung eines temporären Verzeichnisses?
MK Safi

73

Für eine robustere Lösung verwende ich so etwas wie das Folgende. Auf diese Weise wird das temporäre Verzeichnis nach dem Beenden des Skripts immer gelöscht.

Die Bereinigungsfunktion wird für das EXITSignal ausgeführt. Das garantiert, dass die Bereinigungsfunktion immer aufgerufen wird, auch wenn das Skript irgendwo abgebrochen wird.

#!/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
...

Verzeichnis des Bash-Skripts von hier .

Bash Fallen .


26
FreeBSD Achtung! mktemp auf FreeBSD haben keine Option -p und cleanupwird rm -rf Ihr aktuelles Verzeichnis!
Madfriend

1
Guter Punkt, aktualisiert das Skript, um zu überprüfen, ob das temporäre Verzeichnis erstellt werden konnte.
Ortwin Angermeier

1
@madfriend wirklich? Wenn dies mktempfehlschlägt, WORK_DIRist es leer, was bedeutet, dass der Befehl nur rm -rfohne Argument ist. Ich benutze kein FreeBSD, aber ich wäre ziemlich überrascht, wenn rm -rfes gleichbedeutend wäre mitrm -rf .
jbg

@jbg ja, es scheint mir jetzt auch seltsam - es sollte kein wirklich großes Problem sein. Ich habe möglicherweise eine alte Version dieses Skripts so optimiert, dass ein Pfad zum temporären Verzeichnis relativ zum aktuellen Verzeichnis berechnet wurde, was zum <s> Aussterben der Menschheit </ s> beim Entfernen des aktuellen Verzeichnisses führte.
Madfriend

1
Um es besser zu machen, können Sie ein leeres Verzeichnis vermeiden oder zumindest das Problem in einem Verzeichnis enthalten, indem Sie eine Lösung verwenden, bei der Sie Folgendes tun: 1. TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/')und dann 2 rmdir /tmp/git/"${TMPWORKDIR}".. Wenn die Variable jetzt leer ist, werden Sie immer noch /tmp/git/auf das gesamte System zurückgreifen . Betrachten Sie so etwas in der Antwort und ich werde gerne zustimmen. ;)
Dr. Beco

64

Mein Lieblings-Einzeiler dafür ist

cd $(mktemp -d)

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

19
auch nützlich: pushd $(mktemp -d)...popd
Ponkadoodle

4
@ ArranCudbard-Bell sollte seinrm -r $(pwd)
Piggybox

31
@piggybox Ehrlich gesagt wäre ich sehr vorsichtig bei der Verwendung rm -r $(pwd). Berücksichtigen Sie die Möglichkeit, dass die temporäre Verzeichniserstellung aus irgendeinem Grund fehlschlägt (möglicherweise ist das Dateisystem / tmp voll oder wurde aufgrund eines Fehlers schreibgeschützt erneut bereitgestellt?). Anschließend cd $(mktemp -d)wird ausgewertet, cdwelche Änderungen am Home-Verzeichnis des Benutzers vorgenommen werden, die anschließend gelöscht werden.
Jules

1
Es kann sicher sein mitif pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi
AndreyS Scherbakov

9

Das folgende Snippet erstellt sicher ein temporäres Verzeichnis ( -d) und speichert seinen Namen im TMPDIR. (Eine beispielhafte Verwendung von TMPDIRVariablen wird später im Code gezeigt, wo sie zum Speichern von Originaldateien verwendet wird, die möglicherweise geändert werden.)

Die erste trapZeile führt den exit 1Befehl aus, wenn eines der angegebenen Signale empfangen wird. In der zweiten trapZeile wird $TMPDIRder Exit des Programms (sowohl normal als auch abnormal) entfernt (bereinigt ). Wir initialisieren diese Traps, nachdem wir überprüft haben, ob es mkdir -dgelungen ist, ein versehentliches Ausführen des Exit-Traps $TMPDIRin einem unbekannten Zustand zu vermeiden .

#!/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
Während dies eine interessante Lösung für die Fehlerbehandlung ist, wäre eine etwas ausführlichere Erläuterung der Vorteile und möglichen Mängel hilfreich.
Murphy

1.) -dsucht nach Verzeichnissen. 2.) Die Beendigung ist bereits die Standardeinstellung für diese Signale.
10.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.