Dalam sistem file di mana nama file berada di UTF-8, saya punya file dengan nama yang salah; itu ditampilkan sebagai D�sinstaller
:, nama aktual menurut zsh D$'\351'sinstaller
:, Latin1 untuk Désinstaller
, itu sendiri barbarisme Perancis untuk "uninstall." Zsh tidak akan cocok dengan itu [[ $file =~ '^.*$' ]]
tetapi akan mencocokkannya dengan globbing *
- ini adalah perilaku yang saya harapkan.
Sekarang saya masih berharap untuk menemukannya ketika menjalankan find . -name '*'
- sebenarnya, saya tidak akan pernah berharap nama file gagal tes ini. Namun, dengan LANG=en_US.utf8
, file tersebut tidak muncul, dan saya harus set LANG=C
(atau en_US
, atau ''
) untuk itu untuk bekerja.
Pertanyaan: Apa implementasi di belakang, dan bagaimana saya bisa memprediksi hasil itu?
Informasi: Arch Linux 3.14.37-1-lts, find (GNU findutils) 4.4.2
convmv
untuk mengonversi nama file ke utf-8?[[ $file =~ '^.*$' ]]
gagal untuk menggunakanrecode
nama file, tapi sekarang saya akan melihat ke dalamconvmv
jika perlu. Terima kasih.Jawaban:
Itu tangkapan yang sangat bagus. Dari sekilas melihat kode sumber untuk menemukan GNU, saya akan mengatakan ini bermuara pada bagaimana
fnmatch
berperilaku pada urutan byte yang tidak valid (pred_name_common
dalampred.c
):Kode ini menguji nilai pengembalian
fnmatch
untuk kesetaraan dengan 0, tetapi tidak memeriksa kesalahan; ini menghasilkan kesalahan yang dilaporkan sebagai "tidak cocok".Telah disarankan, bertahun-tahun yang lalu, untuk mengubah perilaku fungsi libc ini untuk selalu mengembalikan true pada
*
pola, bahkan pada nama file yang rusak, tetapi dari apa yang saya tahu ide itu pasti telah ditolak (lihat utas mulai di https : //sourceware.org/ml/libc-hacker/2002-11/msg00071.html ):Seperti yang disebutkan oleh Stéphane Chazelas dalam komentar, dan juga di utas tahun 2002 yang sama, ini tidak konsisten dengan ekspansi glob yang dilakukan oleh shell, yang tidak tersumbat pada karakter yang tidak valid. Mungkin yang lebih membingungkan adalah kenyataan bahwa membalikkan tes hanya akan cocok dengan file yang memiliki nama yang rusak (buat file dalam bash with
touch $'D\351marrer' $'Touch\303\251' $'\346\227\245\346\234\254\350\252\236'
):Jadi, untuk menjawab pertanyaan Anda, Anda bisa memperkirakan ini dengan mengetahui perilaku Anda
fnmatch
dalam hal ini, dan mengetahui bagaimanafind
menangani nilai pengembalian fungsi ini; Anda mungkin tidak bisa mengetahuinya hanya dengan membaca dokumentasi.sumber
*
itu maka itu akan menjadi tidak konsisten denganD*staller
.D*staller
akan cocok$'D\351sinstaller'
juga seperti itu di gumpalan semua kerang yang telah saya uji. Mengingat bahwa perilaku fnmatch GNU tidak konsisten dengan perilaku GNU shell, saya akan mengatakan itu bug..
hanya cocok dengan karakter yang valid dalam pengkodean — maka harapan saya yang.*
tidak cocok dengan string yang tidak valid — tetapi saya tidak dapat menemukan spesifikasi yang cocok untuk bintang globbing.-name '*'
cocok dengan semua file, termasuk nama yang rusak), jadi mungkin versi BSDfnmatch
, yang tidak mengklaim POSIX.2 cnoformance, tidak seperti versi GNU, memiliki interpretasi yang berbeda, dan bisa dibilang lebih waras, tentang apa yang harus dilakukan pada karakter yang tidak valid.temukan
-name
opsi menggunakan notasi pencocokan pola shell untuk melakukan pencocokan nama file.*
adalah pola yang cocok dengan banyak karakter , harus cocok dengan untaian karakter nol atau lebih.find
menggunakan fnmatch untuk memeriksa pencocokan pola, sehingga Anda dapat menggunakan ltrace untuk memeriksa hasilnya:Dengan
D\351sinstaller
,fnmatch
kembali-1
, menunjukkan bahwa itu tidak cocok. Karakter seperti yang validሒaa
akan dicocokkan.Dalam kasus Anda, dengan
UTF-8
lokal,\351
adalah karakter yang tidak valid, menyebabkan pencocokan pola gagal.sumber
ltrace
. Saya memang tahustrace
, tetapiltrace
baru bagi saya. Menyenangkan!