Menghindari kesalahan karena tanda bintang yang tidak dikembangkan

16

Dalam bash saya sering menggunakan for-loop seperti berikut ini

for file in *.type; do 
  sommecommand "$file"; 
done;

untuk melakukan operasi untuk semua file yang cocok *.type. Jika tidak ada file dengan akhiran ini ditemukan di direktori yang berfungsi tanda bintang tidak diperluas dan biasanya saya akan mendapatkan pesan kesalahan mengatakan bahwa seseorang tidak menemukan file. Saya dapat segera memikirkan beberapa cara untuk menghindari kesalahan ini. Namun menambahkan persyaratan sepertinya tidak terlalu elegan. Apakah ada cara yang singkat dan bersih untuk mencapai ini?

kelas tinggi
sumber

Jawaban:

20

Ya, jalankan perintah berikut:

shopt -s nullglob

itu akan membatalkan pertandingan dan tidak ada kesalahan yang dipicu.

  • jika Anda ingin perilaku ini secara default, tambahkan perintah di ~/.bashrc
  • jika Anda ingin mendeteksi gumpalan null di shell POSIX, coba

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done

Lihat http://mywiki.wooledge.org/NullGlob

Gilles Quenot
sumber
1
Perhatikan bahwa sebenarnya mungkin ada file yang dipanggil *.txt. Akan sangat berharga untuk memeriksa jika file tersebut ada.
Chris Down
pos diedit sesuai.
Gilles Quenot
@ChrisDown Perhatikan bahwa komentar yang sama dengan jawaban Anda berlaku di sini (dengan konsekuensi yang berpotensi lebih parah karena breakalih - alih continue).
Stéphane Chazelas
6

Di bash, Anda dapat menggunakan shopt -s nullglobuntuk memperluas ke array kosong jika tidak ada yang cocok.

Di shell POSIX tanpa nullglob, Anda dapat menghindari masalah ini dengan memeriksa bahwa nama file yang diteruskan benar-benar ada dengan memiliki [ -e "$file" ] || [ -L "$file" ] || continuesebagai bagian pertama dari forloop Anda .

Chris Down
sumber
1
Perhatikan bahwa itu tidak akan sepenuhnya setara karena [ -eakan mengembalikan false untuk file yang tidak dapat diakses atau file yang merupakan symlink ke file yang tidak dapat diakses atau tidak ada.
Stéphane Chazelas
@StephaneChazelas, beri tahu poin tentang symlink. Tapi apa yang ada dalam pikiran Anda dengan "file tidak dapat diakses"? Bahkan jika saya chmod 0 the_file, [ -e the_file ]masih mengevaluasi benar, jadi itu pasti sesuatu yang lain.
dubiousjim
1
kirim edit untuk menangani symlink yang rusak. harap itu ok
dubiousjim
2
@dubiousjim mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ],. x / a tidak dapat diakses tetapi karena x dapat dibaca x / * akan berkembang.
Stéphane Chazelas
@StephaneChazelas, bagus, terima kasih sudah menjelaskan.
dubiousjim
4

Teknik biasa untuk kerang yang tidak memiliki nullglobpilihan adalah

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

Ekstra [*].typeadalah untuk menutupi kasus di mana ada satu file yang dipanggil *.typedi direktori saat ini.

Sekarang, jika Anda ingin memasukkan file dot, itu menjadi lebih rumit .

Saya percaya bahwa teknik ini diciptakan oleh Laura Fairhead di usenet beberapa tahun yang lalu.

Stéphane Chazelas
sumber
0

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

Ini menghilangkan forloop dan globbing shell dari persamaan sepenuhnya. findakan mengeksekusi -execperintah sekali per pertandingan, dan jika tidak ada pertandingan, itu tidak akan pernah dieksekusi. The -maxdepth 0menginstruksikan menemukan tidak recurse ke dalam subdirektori bernama jalan-argumen ( .dalam hal ini).

Kelemahannya adalah ia melibatkan aplikasi lain, meskipun ada yang hadir di hampir setiap sistem Linux di luar sana (dan mungkin sebagian besar Unix juga).

sebuah CVn
sumber