Di Linux,
cd /tmp
mkdir foo; cd foo
Sekarang, berjalan
find . -name 'foo'
tidak memberikan hasil. Padahal sedang berjalan
find /tmp/foo -name 'foo'
Memberikan hasil /tmp/foo
yang tidak masuk akal bagi saya. Adakah yang bisa menjelaskan mengapa?
./
tidak cocokfoo
find
.bar
yang mengarah ke filefoo
yang berada di luar jalur pencarian. Haruskah itu cocok atau tidak?.
dan/tmp/foo
tidak sama - keduanya adalah dua tautan keras berbeda ke direktori yang sama;find /tmp/foo/. -name 'foo'
juga tidak menemukan apa pun.find /tmp/foo -name 'foo'
, saya meminta bash untuk menemukan di direktori/tmp/foo
, file yang namanya "foo". Karena direktori/tmp/foo
tersebut kosong, seharusnya tidak mengembalikan apa pun. Saya tidak mengerti mengapa ia kembali/tmp/foo
. Di sisi lain, ketika saya menjalankanfind . -name 'foo'
, saya meminta bash hal yang sama, yaitu, menemukan file di direktori saat ini (yang kebetulan/tmp/foo
), yang namanya 'foo', dan tidak mengembalikan apa pun yang masuk akal.Jawaban:
find
melintasi pohon direktori yang ditentukan, dan mengevaluasi ekspresi yang diberikan untuk setiap file yang ditemukannya. Traversal dimulai pada jalur yang diberikan. Berikut ringkasan carafind . -name foo
pengoperasian:.
.
) cocok dengan polanyafoo
? Tidak, jadi jangan lakukan apa-apa.Kebetulan itu
/tmp/foo
adalah nama lain untuk direktori yang sama. Tapifind
tidak tahu itu (dan tidak seharusnya mencoba mencari tahu)..
, dan untuk setiap entri, lakukan proses traversal..
dan..
, yangfind
tidak melintasi secara rekursif. Jadi pekerjaan selesai.Dan
find /tmp/foo
:/tmp/foo
foo
) cocok dengan polanyafoo
? Ya, jadi kondisinya cocok./tmp/foo
, dan untuk setiap entri, lakukan proses traversal..
dan..
, yangfind
tidak melintasi secara rekursif. Jadi pekerjaan selesai.Kebetulan itu
.
dan/tmp/foo
direktori yang sama, tetapi itu tidak cukup untuk menjamin bahwafind
memiliki perilaku yang sama pada keduanya. Thefind
perintah memiliki cara untuk membedakan antara jalur ke file yang sama; yang-name
predikat adalah salah satunya.find /tmp/foo -name foo
cocok dengan direktori awal serta file apa pun di bawahnya yang dipanggilfoo
.find . -name .
hanya cocok dengan direktori awal (.
tidak pernah dapat ditemukan selama traversal rekursif).sumber
.
dan..
. (Jikafind
dilalui.
secara berulang, itu akan berakhir melalui direktori lagi dan lagi dan lagi dan ...).
dan..
bukan hanya notasi khusus, mereka muncul sebagai entri direktori.Tidak ada normalisasi argumen baris perintah sebelum tes diterapkan. Dengan demikian hasilnya berbeda tergantung pada jalur yang digunakan (jika symlinks terlibat):
Dalam "kasus Anda" kedua panggilan akan memberikan hasil yang sama yang mungkin (lebih) membingungkan. Anda dapat menggunakan
-mindepth 1
jika Anda ingin titik awal diabaikan (mungkin non-POSIX).sumber
-mindepth 1
bekerja. Namun, saya masih tidak mengerti mengapafind . -name 'foo'
danfind /tmp/foo -name 'foo'
berperilaku berbeda.(gnu) find menunjukkan kecocokan apa pun yang ditemukan di dalam jalur yang disediakan untuk perintah karena ia memulai perbandingannya dengan argumen commandline, turun lebih dalam ke struktur direktori dari sana (dengan demikian,
-maxdepth 0
membatasi pengujian hanya pada level dasar atau argumen commandline saja, sedangkan-mindepth 1
melewatkan argumen baris perintah seperti yangman find
dijelaskan). Ini adalah alasan mengapafind /tmp/foo -name 'foo'
akan menghasilkan satu kecocokan bahkan jika direktori itu sendiri kosong.find . -name 'foo'
di sisi lain tidak akan menghasilkan hasil apa pun karena.
(dot) adalah file khusus yang bertindak seperti hardlink ke inode yang sama/tmp/foo
- itu seperti nama file yang terpisah (meskipun khusus) dan bukan tautan simbolis atau ekspresi yang dikenakan ekspansi pathname oleh shell. Oleh karena itu, tes pertama yang diterapkan oleh find ke argumen commandline dalam contoh yang diberikan tidak akan menunjukkan kecocokan, karena.
memang tidak cocok dengan pola nama yang didefinisikan dalam-name 'foo'
. Tidak juga/tmp/foo/.
karena tes untuk suatu-name
pola dilakukan hanya pada nama dasar jalan (lihatman find
), yang di sini lagi adalah.
.Sementara perilaku ini mungkin tidak diharapkan atau muncul intuitif dari perspektif pengguna (dan ya, itu membuat saya bingung juga pada awalnya), itu bukan merupakan bug tetapi sesuai dengan logika dan fungsionalitas yang dijelaskan dalam man dan halaman info untuk ( gnu) temukan.
sumber
Saya sudah mencoba mengomentari jawaban Gilles, tetapi terlalu lama untuk memuat komentar. Untuk alasan ini, saya meletakkannya sebagai jawaban untuk pertanyaan saya sendiri.
Penjelasan Gilles (dan juga Shevek) jelas dan masuk akal. Titik kunci di sini adalah bahwa tidak hanya
find
mencoba mencocokkan nama file untuk file di dalam jalur yang diberikan (secara rekursif), tetapi juga, ia mencoba untuk mencocokkan nama dasar dari jalur yang diberikan sendiri.Di sisi lain, apakah ada bukti bahwa ini adalah cara yang
find
seharusnya berfungsi, daripada menjadi bug? Menurut pendapat saya, akan lebih baik jika tidak membuat hasil tidak konsisten untukfind .
danfind ABSOLUTE-PATH
karena ketidakkonsistenan selalu membingungkan dan dapat menyia-nyiakan pengembang banyak waktu mencoba untuk mencari tahu "apa yang salah". Dalam kasus saya, saya sedang menulis skrip, dan path diambil dari variabel. Jadi agar skrip saya berfungsi dengan baik, yang bisa saya pikirkan adalah menulisfind $path/. -name 'pattern'
.Akhirnya, saya pikir mendapatkan hasil yang konsisten untuk
find
dapat dicapai dengan selalu mengganti.
dengan direktori saat ini sebelum melanjutkan.sumber
Tidak ada objek yang disebutkan
foo
dalam direktori tempat Anda memulai pencarian relatif.Anda benar dengan menganggap bahwa
gfind
bermasalah ketika melaporkan/tmp/foo
ketika menggunakan nama absolut sebagai direktori awal.Gfind
memiliki berbagai penyimpangan dari standar, sepertinya Anda menemukan yang lain. Ketika Anda menyukai solusi yang lebih standar, saya sarankansfind
itu adalah bagian darischilytools
.-name
berlaku untuk hasil pencarian direktori. Tidak satu pun dari dua kasus yang Anda sebutkan akan mengembalikan entri direktorifoo
darireaddir()
operasi.sumber
find --version
: find (GNU findutils) 4.4.2 Hak Cipta (C) 2007 Free Software Foundation, Inc. Lisensi GPLv3 +: GNU GPL versi 3 atau lebih baru < gnu.org/licenses/gpl.html >find
(POSIX bersertifikat),gfind
dansfind
; masalahnya hanya ada saat Anda menggunakangfind
. Di Linux,gfind
tidak diinstal di bawah nama asli tetapi di bawah namafind
.find /tmp/foo -name foo
output/tmp/foo
. (Cc @York) Ini adalah perilaku OpenBSDfind
, GNUfind
, BusyBoxfind
, Solarisfind
, dan semua yang sesuai dengan POSIX lainnyafind
(“Primer harus dievaluasi sebagai benar jika nama file dari nama file yang diperiksa cocok dengan pola (…)” - ketika nama file adalah salah satu yang disahkan sebagai operan jalur, tidak adareaddir
panggilan yang terlibat).