Menemukan dir tmp yang benar di berbagai platform

46

Saya memiliki skrip yang perlu membuat file sementara untuk pekerjaannya, dan membersihkannya sendiri. Pertanyaan saya adalah tentang menemukan direktori basis yang tepat untuk file sementara.

Skrip harus bekerja pada beberapa platform: Git Bash (Windows), Solaris, Linux, OSX. Pada setiap platform, direktori temp yang disukai diekspresikan secara berbeda:

  • Windows: %TMP%(dan mungkin %TEMP%)
  • OSX: $TMPDIR
  • Linux, UNIX: seharusnya $TMPDIRtetapi tampaknya tidak disetel pada beberapa sistem yang saya coba

Jadi dalam skrip saya, saya menambahkan boilerplate ini:

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

Ini sepertinya terlalu membosankan. Apakah ada cara yang lebih baik?

Hentikan bahaya yang berkelanjutan pada Monica
sumber
6
Cukup gunakan ${TMPDIR-/tmp}pada Unix-likes. TMPDIRapakah ada (oleh sistem atau administrator atau pengguna) untuk memberi tahu Anda kapan tidak digunakan /tmpuntuk file sementara.
Stéphane Chazelas

Jawaban:

72

Cara yang sedikit lebih portabel untuk menangani file sementara adalah dengan menggunakan mktemp. Ini akan membuat file sementara dan mengembalikan jalurnya untuk Anda. Misalnya:

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

Anda dapat menggunakannya dalam skrip dengan mudah:

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

Membaca halaman manual, Anda harus dapat mengatur opsi sesuai dengan kebutuhan Anda. Misalnya:

  • -d membuat direktori alih-alih file.
  • -u menghasilkan nama, tetapi tidak membuat apa pun.

Menggunakan -uAnda dapat mengambil direktori sementara dengan cukup mudah dengan ...

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

Informasi lebih lanjut mktemptersedia di sini .

Edit mengenai Mac OS X: Saya belum pernah menggunakan sistem Mac OSX, tetapi menurut komentar oleh Tyilo di bawah ini, sepertinya Mac OSX mktempmengharuskan Anda untuk menyediakan templat (yang merupakan argumen opsional di Linux). Mengutip:

Templat dapat berupa nama file apa pun dengan sejumlah "X" yang ditambahkan, misalnya /tmp/temp.XXXX. "Xs" yang tertinggal diganti dengan nomor proses saat ini dan / atau kombinasi huruf yang unik. Jumlah nama file unik yang dapat dikembalikan mktemp tergantung pada jumlah "Xs" yang disediakan; enam "Xs" akan menghasilkan mktemp memilih 1 dari 56800235584 (62 ** 6) kemungkinan nama file.

Halaman manual juga mengatakan bahwa implementasi ini terinspirasi oleh halaman manual OpenBSD untuk mktemp. Oleh karena itu, perbedaan yang serupa mungkin diamati oleh pengguna OpenBSD dan FreeBSD (lihat bagian History ).

Sekarang, seperti yang mungkin Anda perhatikan, ini mengharuskan Anda untuk menentukan path file lengkap, termasuk direktori sementara yang Anda cari dalam pertanyaan Anda. Masalah kecil ini dapat diatasi menggunakan -tsakelar. Sementara opsi ini tampaknya memerlukan argumen ( prefix), akan muncul yang mktempbergantung pada $TMPDIRsaat diperlukan.

Secara keseluruhan, Anda harus bisa mendapatkan hasil yang sama seperti di atas menggunakan ...

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

Setiap umpan balik dari pengguna Mac OS X akan sangat dihargai, karena saya tidak dapat menguji solusi ini sendiri.

John WH Smith
sumber
OP membahas masalah ini dalam komentar yang sekarang dihapus; Saya khawatir saya tidak bisa memberikan jawaban untuk sistem yang membutuhkan gitbashuntuk mendapatkan antarmuka shell, karenanya "sedikit". Saya sebenarnya tidak dapat mengetahui di mana file temp disimpan pada sistem Windows ...
John WH Smith
1
juga. Beberapa orang gila c:\User\Name\..............\stuff. Dan mungkin ada 100 dari mereka. Namun, beberapa distro linux mendekati tingkat kegilaan yang sama /var. Saya penasaran. Itu menurut saya sebagai cara yang aneh untuk mengatakan itu semua - dalam pengalaman saya frustrasi sangat portabel, dan kenyamanan kurang begitu. Jawaban yang sangat bagus.
mikeserv
1
Setahun yang lalu saya menulis skrip Bash untuk memanipulasi file Windows Restore Point yang berfungsi pada Win2K hingga WinXP (versi yang lebih baru menangani hal-hal itu secara berbeda). Script saya menggunakan WINDOWS/Tempatau Windows/Tempsebagai direktori default untuk file tempnya; direktori itu juga ada di mesin Windows 7. Tapi skrip saya memungkinkan pengguna untuk memasok dir temp alternatif pada baris perintah.
PM 2Ring
Ini tidak akan berfungsi pada OS X, karena Anda harus menyediakan template mktemp.
Tyilo
1
Sejak El Capitan, mktemphanya berfungsi: sederhana mktempmengembalikan file, dan mktemp -dmengembalikan direktori; tidak diperlukan templat. The pengguna tidak diperbarui sekalipun.
Franklin Yu
9

Jika Anda mencari hal yang sama di baris yang lebih sedikit ...

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

Anda bisa menulis ini dalam satu.

frostschutz
sumber
Anda mungkin juga harus menguji apakah itu dapat ditulisi.
frostschutz
@janos: Dan jika semuanya gagal, minta pengguna untuk menyediakan path untuk file temp, atau izinkan mereka untuk menentukan satu di baris perintah.
PM 2Ring
6

Anda mungkin melakukannya:

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

Shell harus menemukan direktori yang dapat dieksekusi di salah satu dari 4 alternatif atau keluar dengan kesalahan yang berarti. Namun, POSIX mendefinisikan $TMPDIRvariabel (untuk sistem XCU) :

TMPDIR Variabel ini harus mewakili nama path direktori yang tersedia untuk program yang membutuhkan tempat untuk membuat file sementara.

Itu juga membutuhkan /tmpjalan.

mikeserv
sumber
1
Ini adalah satu-satunya jawaban yang benar di sini IMO. Tidak tahu apa yang dilakukannya duduk di bawah tanpa suara ...
Graeme
2
@ Greme: mungkin karena itu sama sekali tidak dapat dibaca?
ssc
Saya membenarkan tetapi kemudian mencabutnya-- ya, jawaban ini berantakan, Tampaknya berada di jalur yang bermanfaat, tetapi sama sekali tidak jelas apa yang coba dilakukan oleh snippit kode - baris pertama adalah komentar dan yang kedua satu kesalahan (dalam bash, toh). Bisa menggunakan beberapa pekerjaan.
Don Hatch
Oh saya mengerti, versi pertama dari jawabannya lebih jelas (masih ada kesalahan pada baris ke-2 jika Anda benar-benar mencoba menjalankannya) ... dan kemudian serangkaian pengeditan benar-benar menghancurkan sampel kode sehingga sekarang menjadi omong kosong. Bisa menggunakan satu atau dua pas lagi :-)
Don Hatch