temukan tidak rekursif ketika file di atas

8

Bayangkan sebuah pohon sumber. Ada file xml di mana-mana.

Tetapi karena ada XYZ.xml pada akar pohon ini, ia tidak akan menemukan file xml saya.

find -iname *.xml

kembali

./XYZ.xml

dari pada

./XYZ.xml
./a/b/c/bob.xml
./b/d/top.xml
Olivier Toupin
sumber
1
Dari man find: Harap dicatat bahwa Anda harus mengutip pola sebagai hal yang biasa, jika tidak, shell akan memperluas karakter wildcard di dalamnya.
artdanil

Jawaban:

18
find -iname '*.xml'

Jika tidak, shell mengembang Anda *.xmluntuk XYZ.xml, dan perintah yang benar-benar dijalankan adalah

find -iname XYZ.xml

Alasan ini berfungsi jika tidak ada file XML di direktori saat ini adalah bahwa shell umumnya membiarkan wildcard tidak diperluas jika tidak cocok dengan apa pun. Secara umum, setiap kali Anda ingin wildcard untuk diperluas oleh program lain selain shell (misalnya dengan find, tar, scp, dll) Anda perlu untuk mengutip mereka sehingga shell tidak akan mencoba untuk memperluas mereka sendiri.

cjm
sumber
1
Thx, itu sangat sederhana, tapi saya sudah bertanya-tanya bagaimana cara mengatasinya selama berbulan-bulan. Saya menemukan itu benar-benar aneh, dan menjadi perilaku yang sangat tidak konsisten, tetapi sekarang saya mengerti karena itu tidak ditemukan, tetapi kesalahan bash.
Olivier Toupin
2
Ini bukan "kesalahan" bash per-se tetapi milik Anda karena tidak mengutip wildcard yang ingin Anda sampaikan sebagai argumen. Ini berlaku untuk semua program yang menerima input shell. Shell mengekspansi mereka sebagai gumpalan kecuali mereka dikutip atau melarikan diri.
Caleb
1
Saya kira Olivier memaksudkannya dalam arti, bahwa itu adalah masalah bash, bukan masalah find.
pengguna tidak dikenal
6

Anda perlu mengutip argumen Anda seperti ini:

find ./ -name '*.xml'

sehingga dilewatkan untuk menemukan alih-alih diperluas oleh shell, lalu disahkan untuk menemukan sebagai versi yang diperluas.

Caleb
sumber
1
Ok, jadi jika *.xmltidak cocok dengan apa pun di direktori saat ini, itu diteruskan secara harfiah, itulah sebabnya ia bekerja dalam kasus lain. Jawaban yang sangat membantu.
Eric Wilson
1

Wildcard diperluas oleh shell, bukan oleh perintah. findadalah salah satu dari beberapa perintah yang melakukan pencocokan wildcard yang mirip dengan shell, pada waktunya sendiri.

Saat Anda menjalankan ls *.xml, pertama shell memperluas *.xmlke daftar file yang cocok, misalnya file1.xml file2.xml file3.xml, dan kemudian shell memanggil lsdengan daftar argumen yang dihasilkan file1.xml file2.xml file3.xml. Itu sebabnya Anda melihat daftar nama file yang sama echo *.xml, meskipun echotidak tahu apa-apa tentang file dan tidak peduli apakah argumennya adalah nama file.

Ketika Anda menjalankan find . -name "*.xml":

  1. Shell mengurai baris perintah untuk mengenali karakter khusus dan membaginya menjadi kata-kata dan puntu. Berikut ada hanya daftar kata-kata find, ., -name, *.xmldi mana *dikutip. Sejak *dikutip, itu adalah karakter biasa sejauh menyangkut shell.
  2. Shell berjalan perintah finddengan daftar tertentu argumen: ., -name, *.xml.
  3. findmencari file yang namanya cocok dengan pola *.xmldi direktori mana pun di bawah direktori saat ini.

Ketika Anda menjalankan find . -name *.xmldan tidak ada file yang cocok *.xml:

  1. Shell mem-parsing baris perintah untuk mengenali karakter khusus dan membaginya menjadi kata-kata dan puntu. Berikut ada hanya daftar kata-kata find, ., -name, *.xmldi mana *tidak dikutip.
  2. Karena kata tersebut *.xmlberisi karakter wildcard yang tidak dikutip, shell melakukan pembuatan nama file. Karena tidak ada nama file yang cocok, polanya tetap tidak diperluas.
  3. Shell menjalankan perintah finddengan daftar yang dihasilkan dari argumen, yang ., -name, *.xml.
  4. findmencari file yang namanya cocok dengan pola *.xmldi direktori mana pun di bawah direktori saat ini.

Ketika Anda menjalankan find . -name *.xmldan direktori saat ini berisi file1.xml, file2.xmldan file3.xml:

  1. Shell mem-parsing baris perintah untuk mengenali karakter khusus dan membaginya menjadi kata-kata dan puntu. Berikut ada hanya daftar kata-kata find, ., -name, *.xmldi mana *tidak dikutip.
  2. Karena kata tersebut *.xmlberisi karakter wildcard yang tidak dikutip, shell melakukan pembuatan nama file: *.xmldigantikan oleh daftar nama file yang cocok.
  3. Shell menjalankan perintah finddengan daftar yang dihasilkan dari argumen, yang ., -name, file1.xml, file2.xml, file3.xml.
  4. findmengeluh tentang kesalahan sintaks ketika mencapai file2.xml.

Ketika Anda menjalankan find . -name *.xmldan direktori saat ini berisi satu file yang cocok file.xml:

  1. Shell mem-parsing baris perintah untuk mengenali karakter khusus dan membaginya menjadi kata-kata dan puntu. Berikut ada hanya daftar kata-kata find, ., -name, *.xmldi mana *tidak dikutip.
  2. Karena kata tersebut *.xmlberisi karakter wildcard yang tidak dikutip, shell melakukan pembuatan nama file: *.xmldigantikan oleh daftar nama file yang cocok.
  3. Shell menjalankan perintah finddengan daftar yang dihasilkan dari argumen, yang ., -name, file.xml.
  4. findmelihat perintah yang benar-benar valid, tetapi mungkin itu bukan yang Anda maksudkan: finddiperintahkan untuk mencari file yang dipanggil file.xmldalam direktori apa pun, bukan untuk mencari file yang cocok *.xml.

(Evaluasi dan perluasan Shell memiliki banyak fitur lain. Saya hanya menyebutkan yang relevan di sini.)

(Apa yang saya jelaskan adalah perilaku default dari shell yang paling umum: sh, bash, dash, ksh, ... Beberapa shell dapat dikonfigurasi untuk menampilkan kesalahan alih-alih menjalankan perintah dengan wildcard yang tidak diperluas, atau untuk memperluas wildcard yang tidak cocok menjadi kosong daftar. Tidak ada yang akan membantu di sini.)

Gilles 'SANGAT berhenti menjadi jahat'
sumber
-1

Ini berfungsi pada Solaris 10:

find /directory-to-search/* -prune -name "*gz"

pengguna32445
sumber
Ini tidak akan mencari nama yang diakhiri .xml.
Kusalananda
-2

Silakan coba:

find ./ -name *.xml
Tok
sumber
Saya baru saja mencobanya, hasilnya sama.
Eric Wilson
Saya sudah mencobanya, dan berhasil. Pada GNU bash 4.2.8
bbaja42
3
Ini tidak berfungsi ketika glob cocok dengan apa pun di direktori saat ini. Itu sintaks yang salah! Itu *harus selalu dikutip atau lolos untuk lulus untuk menemukan.
Caleb