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 f
atau -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 find
adalah:
.
./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.10
dan menggunakanfind (GNU findutils) 4.4.2
bash
shell
find
command-substitution
Esref
sumber
sumber
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
"{}"
. Mengapa Anda menggunakanecho
dua kali?echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi
\;Jawaban:
Pertama, cuplikan Anda menjalankan perintah
karena perlu outputnya untuk mengevaluasi substitusi perintah. Karena tidak ada file yang bernama
{}
, ini menghasilkan outputKemudian
find
perintah 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 olehfind
. Cuplikan ini harus dieksekusi oleh shell yang dihasilkan olehfind
, bukan oleh shell yang dimulaifind
, karena ia menerima data darifind
pada baris perintahnya. Karena itu Anda perlu menginstruksikanfind
untuk menjalankan shell:Ini lebih baik, tetapi masih tidak benar. Ini akan bekerja dengan beberapa (tidak semua)
find
implementasi 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 perintahrm -rf /
akan dieksekusi. Untuk meneruskan nama file ke skrip, kirimkan sebagai argumen terpisah.Juga yang pertama
echo
mencetak baris baru setelah titik dua. Gunakanecho -n
(jika shell Anda mendukungnya) atauprintf
untuk menghindari ini.Anda dapat menggunakan
-exec … {} +
untuk mengelompokkan doa shell, yang lebih cepat.sumber
Cara lain untuk mengeksekusi
if; then; else; fi
bersamafind
adalah:sumber