Apakah mungkin untuk membuat 'find -exec' di dalam 'find -exec' yang lain?

14

Sesuatu seperti berikut ini adalah apa yang saya cari, tetapi kode saya tidak berfungsi, tidak peduli bagaimana saya melarikan diri {}dan+ ;

find ./ -maxdepth 1 -type d -name '.*' -exec \
    find {} -maxdepth 1 -type f -name '*.ini' -exec \
        md5sum \{\} \\; \;

Setelah melihat ini Unix - & - pertanyaan Linux , saya menemukan bahwa karya-karya kode berikut, tetapi tidak bersarang menemukan seperti itu, dan saya menduga ada cara yang lebih baik untuk melakukan pekerjaan tertentu.

find ./ -maxdepth 1 -type d -name '.*' \
-exec bash -c 'for x; do
    find "$x" -maxdepth 1 -type f -name "*.ini" \
    -exec md5sum \{\} \;; \
done' _ {} \+

Apakah ada cara untuk membuat sarang find -exectanpa harus menggunakan shell (seperti di atas), dengan semua kutipan aneh dan kendala lolos?

Atau dapatkah ini dilakukan secara langsung dalam satu perintah find, menggunakan campuran dari banyak parameternya?

Peter.O
sumber
4
Meskipun dimungkinkan untuk melakukan apa yang Anda minta, ketika segalanya menjadi kompleks, saya beralih ke skrip shell atau Perl. Cuplikan kode kedua Anda cukup banyak melakukan ini, hanya dengan skrip shell inline. One-liner heroik menghibur, tetapi sulit dipahami, dan karenanya sulit dipertahankan. Kecuali jika ini adalah kesepakatan satu kali yang akhirnya Anda pahami dengan baik, saya tidak dapat melihat alasan yang baik untuk melakukannya selain dari tantangan intelektual.
Warren Young
1
@ Warren Young: Saya tentu tidak berpikir konsepnya kompleks, tapi saya berasumsi maksud Anda tidak ada cara sederhana untuk dilakukan find, tetapi jika findtidak bisa melakukan ini, lalu mengapa findbegitu dihormati (?) Sebagai alat- untuk digunakan untuk mencari file? ... Saya secara subseqeuntly menemukan bahwa find ./ -maxdepth 2 -path '.*/*.ini' -type f -exec md5sum {} \+berfungsi dengan baik dalam situasi saya (referensi jw013 untuk -prunemembawa saya ke ini di halaman manual), tapi saya bertanya-tanya apakah itu metode yang kuat (dalam genera). Saya tidak pernah benar-benar menggunakan find(dalam waktu kurang dari satu tahun Linux) karena locatetelah melakukan hampir semua yang saya butuhkan, jadi itu adalah wilayah yang tidak dikenal.
Peter.O
1
The -pathuji persis apa yang akan saya sarankan. Dengan ini, Anda harus dapat melakukan semua yang Anda inginkan (maaf untuk asosiasi Ace Of Base;))
rozcietrzewiacz

Jawaban:

8

Saya akan mencoba menggunakan pencarian tunggal seperti:

find .*/ -maxdepth 1 -type f -name '*.ini' -execdir md5sum {} +

atau bahkan ( findsama sekali tidak, cukup shell globbing)

md5sum .*/*.ini

walaupun ini tidak memiliki -type fpemeriksaan jadi hanya berfungsi jika Anda tidak memiliki direktori / non-file yang berakhiran .ini. Jika Anda melakukannya, Anda bisa menggunakan

for x in .*/*.ini; do 
    if [ -f "$x" ]; then 
        md5sum "$x"
    fi
done

Namun yang akan kehilangan keuntungan dari hanya membutuhkan satu doa md5sum.

Edit

Untuk metode chaining umum dan aman find, Anda dapat melakukan sesuatu seperti

find <paths> <args> -print0 | xargs -0 -I{.} find {.} <args for second find> [etc.]
jw013
sumber
Saya mendapatkan kesalahan dengan -f(f?), Dan kemudian kesalahan lain dengan -execdir.. Ketika saya mengganti -execdir dengan -exec, dan / atau juga mengganti md5sum dengan print, saya tidak mendapatkan apa-apa ..
Peter.O
Terima kasih, untuk alternatifnya ... tapi saya lebih mencari cara untuk menggunakan ini find... Ini tidak terlalu banyak sehingga saya hanya ingin contoh ini diselesaikan, saya mencari wawasan tentang cara menemukan-fu .. mungkin ada lebih banyak bulu daripada fu di temukan .. (saya tidak tahu, karena saya hampir tidak pernah menggunakannya), dan ini adalah situasi pertama saya benar-benar ingin menggunakannya (untuk file gambar sebenarnya) dan Fitur -exec Saya sudah banyak mendengar tentang tampaknya tidak sekuat rep (?) menyinggung ... (+1 untuk alternatif, meskipun) .. tapi findcontoh Anda tidak bekerja (masih )
Peter.O
Saya mendapatkan kesalahan ini untuk findperintah: ... find: The relative path ~ / bin 'termasuk dalam variabel lingkungan PATH, yang tidak aman dalam kombinasi dengan aksi -execdir dari find. Silakan hapus entri itu dari $ PATH` .... Jadi mungkin itu akan berhasil, tetapi saya harus mengatakan saya telah mencoba untuk menyingkirkan itu ~ / bin untuk sementara waktu sekarang ... Saya harus mengambil lebih banyak serius melihatnya ... Saya tidak tahu di mana saya telah mengaturnya ... ada ide di mana ia mungkin bersembunyi; yang ~/bindi PATH saya
Peter.O
Saya pikir kekuatan findterbaik dihargai dalam situasi yang tidak dapat dilakukan sepenuhnya dengan gumpalan, tetapi karena situasi seperti itu jarang terjadi, saya biasanya tidak perlu menemukan banyak.
jw013
Oke .. itu poin yang menarik dan bagus (tentang menggunakan gumpalan) ...
Peter.O
2

Masalah awal Anda tidak memerlukan panggilan menemukan secara rekursif tapi saya kira itu bukan intinya.

Saya percaya itu tidak mungkin untuk memanggil menemukan secara rekursif dengan cara yang Anda inginkan.

Yang berikut ini tidak memanggil find secara rekursif (atau bersarang, apa pun namanya), tetapi tidak bisakah Anda hanya mengambil set hasil dari temuan pertama dan memberinya makan ke yang kedua? Inilah yang akan saya lakukan secara naluriah:

find `find ./ -maxdepth 1 -type d -name '.*'` \
    -maxdepth 1 -type f -name '*.ini' -exec md5sum {} \;

Anda juga dapat menggunakan xargsuntuk mengeksekusi temuan kedua.

Memperbarui:

Saya ingin menambahkan itu karena sebagian besar utilitas UNIX mengambil beberapa argumen nama file alih-alih satu, Anda biasanya dapat menghindari -execsemuanya:

md5sum `find \`find ./ -maxdepth 1 -type d -name '.*'\` -maxdepth 1 -type f -name '*.ini'`

Ketika bersarang backticks Anda hanya menambahkan garis miring terbalik \sebelum yang dalam.

Jika kita membayangkan bahwa md5sumhanya membutuhkan satu argumen nama file, kita selalu dapat membungkusnya dalam satu forlingkaran:

for f in `find \`find ./ -maxdepth 1 -type d -name '.*'\` -maxdepth 1 -type f -name '*.ini'`
do
    md5sum $f
done

Perhatikan bahwa ini menjadi lebih sulit jika nama file / direktori dimulai dengan -atau mengandung spasi yang terlibat. Utilitas UNIX tidak bermain baik dengan mereka. Dalam hal itu menambahkan ./, --atau kutipan diperlukan.

Jelas contoh asli bukan yang baik, karena kita bisa melakukan:

md5sum .*/*.ini
jepret
sumber
1
Anda telah memberikan gambaran umum yang baik tentang situasinya, tetapi semua findmetode yang ditampilkan mendapatkan kesalahan ketika file / direktori berisi spasi ... md5sum .*/*.iniBerfungsi dengan baik ... Saya mulai mendapatkan perasaan umum bahwa * Warren Young * berkomentar tentang hal-hal yang 'kompleks' untuk findterjadi di awal permainan :), tapi saya berasumsi finddatang sendiri ketika tes kondisi lebih rumit, tetapi sejauh bersarang -exec, saya cukup baik menjatuhkan ide, karena tampaknya ada cara yang lebih sederhana untuk melakukannya .. (tetapi perl tidak "sederhana" bagi saya (belum) ...
Peter.O
0

Setidaknya saya berhasil membuat sarang untuk menemukan perintah:

find ~ -maxdepth 1 -type d -name '.*' -execdir \
    find {} -maxdepth 1 -type f -name '*.ini' \;

Tapi saya tidak memecahkan untuk memanggil -exec (dir) lain - panggilan dari sana.

Pengguna tidak diketahui
sumber
Ya, itulah masalah saya sebenarnya :)
Peter.O
Ya, tapi tidak bersarang 3 tidak sama dengan tidak bersarang 2. :)
pengguna tidak diketahui