Bagaimana cara membuat direktori sementara?

229

Saya menggunakan untuk membuat tempfile, menghapusnya dan membuatnya kembali sebagai direktori:

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

Masalahnya adalah, proses lain mungkin mendapatkan nama yang sama X, jika secara tidak sengaja mengeksekusi tempfile setelah satu proses rm -f Xdan tepat sebelumnya mkdir X.

Xiè Jìléi
sumber

Jawaban:

341

Gunakan mktemp -d. Itu membuat direktori sementara dengan nama acak dan memastikan file itu belum ada. Anda harus ingat untuk menghapus direktori setelah menggunakannya.

moinudin
sumber
25
Saya harus menggunakanmktemp -d -t <prefix>
Heath Borders
17
Ini adalah OS X vs Linux. Lihat pertanyaan ini untuk versi yang berfungsi pada keduanya: unix.stackexchange.com/questions/30091/…
jwhitlock
2
Juga, lihat jawaban di bawah ini oleh Ortwin, karena itu memastikan pembersihan juga dilakukan.
Mathiasdm
5
Mengapa Anda mengatakan "Anda harus ingat untuk menghapus direktori setelah menggunakannya."? Bukankah itu agak mengalahkan tujuan menggunakan direktori temp?
MK Safi
73

Untuk solusi yang lebih kuat saya menggunakan sesuatu seperti berikut ini. Dengan cara itu direktori temp akan selalu dihapus setelah skrip keluar.

Fungsi pembersihan dijalankan pada EXITsinyal. Itu menjamin bahwa fungsi pembersihan selalu dipanggil, bahkan jika skrip dibatalkan di suatu tempat.

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

Direktori skrip bash dari sini .

Bash traps .

Ortwin Angermeier
sumber
26
Perhatian FreeBSD! mktemp di FreeBSD tidak memiliki opsi -p, dan cleanupakan rm -rf direktori Anda saat ini!
madfriend
1
Poin bagus, perbarui skrip untuk memeriksa apakah temp temp bisa dibuat.
Ortwin Angermeier
1
benar-benar teman? jika mktempgagal, WORK_DIRakan kosong, artinya perintah hanya akan rm -rftanpa argumen. Saya tidak menggunakan FreeBSD tapi saya akan sangat terkejut jika rm -rfitu setara denganrm -rf .
jbg
@ JBG ya, sepertinya aneh bagi saya sekarang juga - itu seharusnya tidak menjadi masalah yang sangat besar. Saya mungkin telah mengubah versi lama skrip ini sehingga jalur ke direktori sementara dihitung relatif ke direktori saat ini, mengakibatkan <s> kepunahan umat manusia </s> penghapusan direktori saat ini.
madfriend
1
Untuk membuatnya lebih baik, Anda dapat menghindari direktori kosong atau setidaknya mengandung masalah dalam direktori menggunakan solusi di mana Anda melakukannya: 1. TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/')dan kemudian 2 rmdir /tmp/git/"${TMPWORKDIR}".. Jika variabelnya kosong sekarang, Anda masih akan kembali ke /tmp/git/tidak ke keseluruhan sistem. Pertimbangkan sesuatu seperti ini dalam jawaban dan saya dengan senang hati akan setuju. ;)
Dr Beco
64

Satu-liner favorit saya untuk ini adalah

cd $(mktemp -d)
Emmett Butler
sumber
10
dan rm $(pwd)? : P
Arran Cudbard-Bell
19
juga berguna: pushd $(mktemp -d)...popd
Ponkadoodle
4
@ ArranCudbard-Bell seharusnyarm -r $(pwd)
piggybox
31
@ piggybox Terus terang, saya akan sangat berhati-hati dalam menggunakan rm -r $(pwd). Pertimbangkan kemungkinan bahwa pembuatan direktori sementara gagal karena alasan apa pun (mungkin sistem file / tmp penuh atau telah di-remount hanya karena kesalahan?); kemudian cd $(mktemp -d)akan mengevaluasi cdperubahan mana ke direktori home pengguna, yang selanjutnya akan dihapus.
Jules
1
Mungkin aman denganif pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi
AndreyS Scherbakov
9

Cuplikan berikut secara aman akan membuat direktori sementara ( -d) dan menyimpan namanya ke dalam TMPDIR. (Contoh penggunaan TMPDIRvariabel ditunjukkan kemudian dalam kode di mana ia digunakan untuk menyimpan file asli yang mungkin akan dimodifikasi.)

Baris pertama trapmenjalankan exit 1perintah ketika salah satu sinyal yang ditentukan diterima. Baris kedua trapmenghapus (membersihkan) jalan $TMPDIRkeluar program (normal dan abnormal). Kami menginisialisasi jebakan ini setelah kami memeriksa yang mkdir -dberhasil menghindari secara tidak sengaja mengeksekusi jebakan keluar dengan $TMPDIRkondisi tidak diketahui.

#!/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
jreisinger
sumber
1
Meskipun ini merupakan solusi yang menarik untuk penanganan kesalahan, penjelasan lebih banyak tentang kelebihan dan kekurangan mungkin akan lebih baik.
Murphy
1.) -dmemeriksa direktori. 2.) Pengakhiran sudah merupakan default untuk sinyal-sinyal tersebut.
ceving