Bagaimana cara menjalankan beberapa perintah saat menggunakan find?

57

Saya mencoba menjalankan beberapa perintah pada hal-hal yang saya temukan, bagaimana saya bisa mencapai ini?

find . -exec cmd1; cmd2

sepertinya tidak berfungsi; itu malah menjalankan cmd2 setelah cmd1 telah dieksekusi pada setiap file.

Tamara Wijsman
sumber

Jawaban:

40

Dalam demonstrasi ini, saya akan menggunakan sh -c 'echo first; false'(atau true) untuk yang pertama -exec. Itu akan memberikan beberapa output dan juga memiliki efek kode keluar yang dipilih. Kemudian echo secondakan digunakan untuk yang kedua. Asumsikan ada satu file di direktori saat ini.

$ find . -type f -exec sh -c 'echo first; false' \; -exec echo second \;
first
$ find . -type f -exec sh -c 'echo first; true' \; -exec echo second \;
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second
$ find . -type f \( -exec sh -c 'echo first; false' \; -false -o -exec echo second \; \)
first
second

Perintah nyata dari jenis ini akan terlihat seperti:

find . -type f \( -exec command1 \; -false -o -exec command2 \; \)

Pada set kedua, tanda kurung yang lolos mengelompokkan dua -execklausa. Di -falseantara mereka memaksa negara uji untuk "salah" dan -omenyebabkan ekspresi selanjutnya (yang kedua -exec) dievaluasi karena -false.

Dari man find:

expr1 expr2
Dua ekspresi berturut-turut diambil untuk digabungkan dengan tersirat "dan"; expr2 tidak dievaluasi jika expr1 salah.

expr1 -a expr2
Sama seperti expr1 expr2.

expr1 -o expr2
Atau; expr2 tidak dievaluasi jika expr1 benar.

Dennis Williamson
sumber
Ah ya, saya lupa -o.
Ignacio Vazquez-Abrams
32

Jika Anda tidak peduli tentang cmd1 dapat mencegah cmd2 dijalankan karena kode kesalahan 0:

find . -exec cmd1 \; -exec cmd2 \;

Satu-satunya cara yang dapat diandalkan untuk mendapatkan kedua perintah untuk selalu menjalankan ini adalah dengan findmemanggil shell yang selanjutnya akan menjalankan perintah secara berurutan:

find . -exec bash -c 'cmd1; cmd2' filedumper {} \;
Ignacio Vazquez-Abrams
sumber
2

Jika Anda tidak keberatan membuat skrip yang memiliki cmd1 dan cmd2, maka cukup ini:

find . -exec myscript {} \;

atau

find . -exec myscript {} +

Gunakan \; atau + tergantung pada apakah skrip saya dapat menangani lebih dari satu file pada satu waktu (menjadi berbulu jika ada spasi dalam nama file, dll).

Menempatkan apa yang Anda lakukan dalam sebuah skrip, dalam pengalaman saya, hampir selalu sepadan. Jika Anda harus melakukannya sekali, Anda harus melakukannya lagi.

Tetapi trik yang rapi adalah dengan menempatkan temuan di dalam skrip:

if [ $# -gt 0 ]; then
    for each; do
        touch $each
    done
else
    find . -exec $0 {} +
fi

Kemudian myscript bekerja pada file apa pun yang Anda berikan sebagai argumen agar bisa berfungsi, tetapi jika Anda tidak memberikan argumen apa pun, itu berjalan temukan dari dir saat ini, dan kemudian menyebut dirinya pada file yang ditemukan. Ini mengatasi fakta bahwa -exec tidak dapat memanggil fungsi shell yang telah Anda tetapkan dalam skrip Anda.

mza
sumber
0

Saya telah mencoba kedua solusi sebelumnya tanpa banyak keberuntungan. Yang ini bekerja dengan baik untuk saya:

$ for i in `find . -exec echo {} \;`; do cmd1 $i; cmd2 $i; done
pengguna9869932
sumber
Ini tidak akan berfungsi jika daftar file terlalu besar.
Alex
-3

coba perintah:

sudo find -name "*[!0-9][1-9].txt" -exec chmod 744 * {} \; -a -exec ls -l {} \; | sort | parallel ls -l
Saptak Das
sumber
4
Eh, itu bukan ide yang bagus. The *di -execbagian akan diperluas untuk semua file dalam direktori saat ini. Terutama saat menjalankan sebagai sudo.
slhck