Saya sedang menulis beberapa skrip dan menulis sesuatu seperti
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
Apa yang terjadi adalah karena kebodohan saya mengeksekusi baris kedua tanpa mengeksekusi yang pertama. Ternyata [-d ""] mengembalikan true dan ekspresi menjadi
rm -rf /*
Untungnya itu hanya mesin uji dan saya bukan sudo, tetapi meskipun saya kehilangan beberapa data
Pertanyaan saya adalah, mengapa [-d ""] kembali benar ?? dokumentasi dengan jelas menyatakan memeriksa apakah ada jalur dan folder
Saya memecahkan masalah dengan menggunakan
[ -e $ARTIFACTS ]
yang tampaknya berhasil
Bersulang
rm -rf $ARTIFACTS
tanpa/*
. Ini juga akan menghapus$ARTIFACTS
direktori, yang baik-baik saja, karena jika saya ingin memastikan bahwa itu ada sebelum memasukkan sesuatu ke dalamnya, saya akanmkdir -p $ARTIFACTS
tetap menjalankannya . Ini juga akan menghapus file tersembunyi di dalamnya$ARTIFACTS
, yang juga baik-baik saja, karena saya tidak akan menulisrm -rf $ARTIFACTS/*
jika$ARTIFACTS
berisi sesuatu yang ingin saya simpan.Jawaban:
1. Dua tes ini menghasilkan true :
menurut POSIX (seperti yang dijelaskan oleh @Tim).
2. Tetapi ini mengembalikan false ( tidak benar seperti yang dinyatakan dalam pertanyaan)
karena
test
dipanggil dengan dua argumen (walaupun yang kedua adalah string kosong).3. Itulah mengapa ini merupakan praktik yang baik untuk digunakan
[[ … ]]
alih-alihtest
([ … ]
), yang disediakan oleh kebanyakan (semua?) Shell saat ini. Konstruk ini memeriksa apakah Anda memberikan cukup argumen (jika tidak menimbulkan kesalahan dan batal)atau hanya berperilaku seperti yang diharapkan:
4. Dan, seperti yang ditunjukkan oleh @Gilles, yang lebih penting adalah menggandakan substitusi kutipan. Jadi
-d "$SOME_UNSET_VAR"
perluas-d ""
dan kembalikan false dengantest
(sama dengan case 2). Karenanya ini juga kompatibel dengan shell Bournesh
:diuji dengan bash 3.00.16 (1) dan 4.1.5 (1)
sumber
[[ … ]]
tapi tidak polossh
. Praktek benar-benar penting adalah untuk menaruh tanda kutip ganda di sekitar substitusi perintah :[ -d "$ARTIFACTS" ]
.Pertanyaan ini sudah dijawab di StackOverflow. Dikatakan bahwa menurut standar POSIX,
test
harus selalu kembali berhasil jika dipanggil dengan tepat satu argumen tidak kosong (dan tidak ada argumen lain).Ini juga harus menjadi kasus dengan
test -e
(dan sebenarnya itu ada di sistem saya), jadi berhati-hatilah.Alih-alih gunakan:
test
kemudian akan dipanggil dengan dua argumen bahkan jika variabelnya kosong dan mengembalikan false dalam kasus ini.sumber
[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]
tidak lebih baik: itu hanya untuk kasus tertentu ketika$ARTIFACTS
kosong, tetapi gagal ketika$ARTIFACTS
mungkin berisi spasi atau\[?*
.[ -d "$ARTIFACTS" ]
adalah cara yang benar untuk melakukannya (atau[[ -d $ARTIFACTS ]]
dalam cangkang yang dimiliki[[ … ]]
).Anda salah . Ini berfungsi karena
$ARTIFACTS
sekarang diatur ke sesuatu.Ketika variabel tidak disetel, lalu ucapkan
atau
akan sama - sama mengevaluasi
true
karena itu menyiratkan perkataandan
masing-masing. (Mengatakan
[ foobar ]
akan selalu dinilai benar.)Pepatah
berguna dalam situasi seperti itu.
help set
akan memberi tahu Anda:sumber
Lihat bahwa Anda menetapkan variabel ARTIFACTS dan Anda memeriksa ARTIFCATS. Mungkin salah ketik?
Bagaimanapun, -d dan -e akan menghasilkan hasil yang sama pada variabel yang tidak disetel.
Karenanya gunakan tanda kutip ganda dan itu akan membantu Anda.
CATATAN: Jika "/ SOME / PATH" Anda memiliki folder dengan spasi, skrip yang Anda sebutkan akan terputus dengan kesalahan "operator biner yang diharapkan".
Contoh:
akan baik-baik saja. Jangan lupa untuk menaruh tanda kutip dalam
rm
doa juga (rm -rf $ARTIFACTS
akan dengan senang hati menghapus/home
kemudian mengeluh tentangbackup/*
tidak ada).Juga, termasuk
-L
cek akan memastikan bahwa itu adalah direktori dan bukan hanya tautan simbolik ke direktori.Pada dasarnya,
sumber