jika perintah dalam find -exec

9

Saya hanya mencoba daftar semua direktori dan file di bawah direktori saat ini dan juga menulis apakah mereka file atau direktori dengan perintah berikut:

find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;

Saya tahu ini adalah perintah yang konyol, saya dapat menggunakan hal-hal lain seperti -type fatau -type d, tetapi saya ingin belajar mengapa potongan kode itu tidak berfungsi seperti yang saya harapkan. Itu hanya mencetak direktori untuk mereka semua. Sebagai contoh sementara output dari findadalah:

.
./dir
./dir/file

output dari kode saya adalah:

. : directory
./dir : directory
./dir/file : directory

Dan output dari

echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`

adalah

dir/file : file

Saya sedang mengerjakan Ubuntu 14.10dan menggunakanfind (GNU findutils) 4.4.2

Esref
sumber
1
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
Costas
1
Terima kasih @ Costas tapi saya tahu bahwa menggunakan bash atau sh saya dapat mencapai tujuan awal saya, tetapi sekarang saya ingin mengerti mengapa jika berperilaku berbeda dengan parameter exec.
Esref
Masukkan argumen ke dalam kutipan "{}". Mengapa Anda menggunakan echodua kali?
Costas
Saya sudah mencobanya dan memberikan hasil yang sama. temukan -exec echo echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi\;
Esref

Jawaban:

13

Pertama, cuplikan Anda menjalankan perintah

echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi

karena perlu outputnya untuk mengevaluasi substitusi perintah. Karena tidak ada file yang bernama {}, ini menghasilkan output

{} :
directory

Kemudian findperintah dijalankan dengan argumen -exec, echo, {}, :, directory, jadi untuk setiap file, itu output nama file diikuti dengan spasi dan : directory.

Apa yang sebenarnya ingin Anda lakukan adalah mengeksekusi snippet shell echo {} :; …pada setiap file yang ditemukan oleh find. Cuplikan ini harus dieksekusi oleh shell yang dihasilkan oleh find, bukan oleh shell yang dimulai find, karena ia menerima data dari findpada baris perintahnya. Karena itu Anda perlu menginstruksikan finduntuk menjalankan shell:

find -exec sh -c 'echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi' \;

Ini lebih baik, tetapi masih tidak benar. Ini akan bekerja dengan beberapa (tidak semua) findimplementasi jika nama file Anda tidak mengandung karakter khusus, tetapi karena Anda menginterpolasi nama file dalam skrip shell, Anda mengizinkan nama file untuk mengeksekusi perintah shell sewenang-wenang, misalnya jika Anda memiliki sebuah file dipanggil $(rm -rf /)maka perintah rm -rf /akan dieksekusi. Untuk meneruskan nama file ke skrip, kirimkan sebagai argumen terpisah.

Juga yang pertama echomencetak baris baru setelah titik dua. Gunakan echo -n(jika shell Anda mendukungnya) atau printfuntuk menghindari ini.

find -exec sh -c 'printf "%s :" "$0"; if [ -f "$0" ]; then echo file; else echo directory; fi' {} \;

Anda dapat menggunakan -exec … {} +untuk mengelompokkan doa shell, yang lebih cepat.

find -exec sh -c 'for x; do printf "%s :" "$x"; if [ -f "$x" ]; then echo file; else echo directory; fi; done' _ {} +
Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Cara lain untuk mengeksekusi if; then; else; fibersama findadalah:

find |
while read p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done
ncomputer
sumber
1
Solusi keren Ini menghindari pola penawaran yang kompleks dan komplikasi subkulit. Anda mungkin sebelumnya telah mendefinisikan fungsi shell, dan menjalankannya pada file yang cocok dengan kondisi "jika".
gerlos