Jawaban muru sesuai dan cocok untuk kasus-kasus di mana kita ingin mencetak sesuatu jika file ditemukan. Untuk kasus umum ketika kita ingin mengeksekusi perintah eksternal, seperti echo
, kita bisa menggunakan -exec
flag.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
Bagian {}
meneruskan nama file ke perintah antara -exec
dan \;
sebagai argumen. Catat \
sebelum ;
- ia mencegah shell dari salah mengartikannya ; di dalam koma penutupan shell menandakan akhir dari perintah, tetapi ketika lolos dengan slash, shell akan memperlakukannya sebagai teks literal untuk diteruskan ke find
perintah dan untuk menemukan perintah itu berfungsi sebagai -exec
argumen penutup flag.
Untuk membangun kondisional if found do this; else do that
semacam itu, kita dapat menggunakan substitusi perintah $()
dan test
perintah (alias [
):
$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"
not found
$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"
found
Mengatasi komentar Dan
Dan di komentar bertanya:
Tidakkah gema "Saya menemukan {}" lebih baik daripada gema "Saya menemukan" {}? Mungkin untuk gema tidak masalah, tetapi jika seseorang menyalin perintah dan mengganti gema dengan perintah lain, mereka mungkin memiliki masalah
Mari kita pahami masalahnya dulu. Biasanya, dalam shell ada konsep pemisahan kata, yang berarti variabel yang tidak dikutip dan parameter posisi akan diperluas dan diperlakukan sebagai item terpisah. Misalnya, jika Anda memiliki variabel var
dan itu berisi hello world
teks, ketika Anda melakukannya touch $var
shell akan memecahnya menjadi dua item yang terpisah hello
dan world
dan touch
akan memahami bahwa seolah-olah Anda mencoba membuat 2 file terpisah; jika Anda melakukannya touch "$var"
, maka shell akan memperlakukan hello world
sebagai satu unit, dan touch
akan membuat satu file saja. Ini penting untuk dipahami bahwa ini terjadi hanya karena cara kerja cangkang.
Sebaliknya, find
tidak menderita perilaku seperti itu, karena perintah diproses dengan find
sendirinya dan dieksekusi oleh execvp()
system call, jadi tidak ada shell yang terlibat. Sementara kurung kurawal memang memiliki arti khusus dalam cangkang, karena mereka muncul di tengah-tengah find
perintah, dan tidak pada awalnya, mereka tidak memiliki arti khusus untuk shell dalam kasus ini. Ini sebuah contoh. Mari kita membuat beberapa nama file yang sulit dan mencoba untuk memberikannya sebagai argumen untuk stat
perintah.
$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt
$ find -type f -exec stat -c "%F" {} \; -print
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt
Seperti yang Anda lihat, stat
menerima nama file yang sulit dengan baik find
, yang merupakan salah satu alasan utama mengapa dianjurkan untuk digunakan dalam skrip portabel, dan terutama berguna ketika Anda melintasi pohon direktori dan ingin melakukan sesuatu dengan nama file yang mungkin berpotensi memiliki karakter khusus di dalamnya. Oleh karena itu, tidak perlu mengutip kurung kurawal untuk perintah yang dieksekusi di find
.
Ini adalah cerita yang berbeda ketika shell terlibat. Terkadang Anda perlu menggunakan shell untuk memproses nama file. Dalam hal itu, mengutip memang akan penting, tetapi penting untuk menyadari bahwa itu bukan masalah menemukan - itu adalah shell yang melakukan pemisahan kata.
$ find -type f -exec bash -c "stat {}" sh \;
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory
Jadi ketika kami mengutip dalam shell , itu akan berhasil. Tapi sekali lagi, itu penting untuk shell, bukan find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
memberitahu menemukan tempat untuk mulai mencari, tetapi tidak ada yang memberi tahu apa yang harus dicari. Sama dengan jawaban tertaut Anda. Apa yang berhasil bagi sayafind /some/path -name xac -print0 -quit | grep -qz . && echo found
? Apakah saya melewatkan sesuatu?