Mengapa menemukan mencetak arahan './' jika tidak ada jalur yang diberikan?

13

Mengapa yang findmencetak mengarah ./ke hasil jika tidak ada jalur yang diberikan?

$ find
./file1
./file2
./file3

Apa alasan untuk tidak mencetak ini?

$ find
file1
file2
file3
no
sumber

Jawaban:

16

The Alasan mengapa Anda melihat ini adalah karena pengembang GNU memilih untuk memberikan "masuk akal" perilaku untuk saat tidak ada jalan yang diberikan. Sebaliknya, POSIX tidak menyatakan bahwa parameternya opsional:find find

The findutilitas akan secara rekursif turun hirarki direktori dari setiap file yang ditentukan oleh jalan , mengevaluasi ekspresi Boolean terdiri dari pendahuluan dijelaskan di bagian operan untuk setiap file yang dihadapi. Setiap operan jalur harus dievaluasi tidak berubah seperti yang disediakan, termasuk semua <slash>karakter tambahan; semua nama path untuk file lain yang ditemukan dalam hierarki harus terdiri dari gabungan dari operan path saat ini, a <slash>jika operan path saat ini tidak berakhir dalam satu, dan nama file relatif terhadap operan path. Bagian relatif tidak boleh mengandung komponen titik atau titik-titik, tidak ada jejakkarakter, dan hanya <slash>karakter tunggal di antara komponen pathname.

Anda dapat melihat perbedaan dalam sinopsis untuk masing-masing. GNU memiliki (seperti konvensi) item opsional dalam tanda kurung:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...]
       [expression]

sementara POSIX tidak menunjukkan bahwa itu bisa opsional:

find [-H|-L] path... [operand_expression...]

Dalam program GNU, itu dilakukan di ftsfind.c:

  jika (kosong)
    {
      / *
       * Kami menggunakan variabel sementara di sini karena beberapa tindakan memodifikasi
       * jalan sementara. Maka dari itu jika kita menggunakan konstanta string,
       * Kami mendapatkan coredump. Contoh terbaik dari ini adalah jika kita katakan
       * "find -printf% H" (perhatikan, bukan "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      return find (defaultpath);
    }

dan literal "."digunakan untuk kesederhanaan. Jadi, Anda akan melihat hasil yang sama dengan

find

dan

find .

karena (dan POSIX setuju) jalur yang diberikan akan digunakan untuk mengawali hasil (lihat di atas untuk rangkuman ).

Dengan sedikit kerja, orang bisa menentukan kapan fitur pertama kali ditambahkan; itu hadir dalam penciptaan awal "findutils" pada tahun 1996 (lihat find.c):

+  /* If no paths are given, default to ".".  */
+  for (i = 1; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
+    process_top_path (argv[i]);
+  if (i == 1)
+    process_top_path (".");
+
+  exit (exit_status);
+}

Dari changelog untuk find 3.8, ini tampaknya

Sat Dec 15 19:01:12 1990  David J. MacKenzie  (djm at egypt)

        * find.c (main), util.c (usage): Make directory args optional,
        defaulting to "."
Thomas Dickey
sumber
11

Biasanya, seseorang melakukan post-processing file dan, dalam hal ini, bisa ada keuntungan besar untuk memulai nama file ./. Secara khusus, jika nama file dimulai dengan -, perintah selanjutnya dapat menafsirkan bahwa nama file opsi. ./hindari itu.

Sebagai contoh, pertimbangkan direktori dengan file-file ini:

$ ls
--link  --no-clobber

Sekarang, bayangkan bagaimana perintah ini bekerja jika nama file diberikan tanpa ./di depan:

$ find -type f -exec cp -t ../ {} +

Kita bisa menggambarkan masalahnya dengan findsendirinya. Mari kita jalankan di direktori yang sama seperti di atas. Karya-karya berikut:

$ find ./*
./--link
./--no-clobber

Berikut ini gagal:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.
John1024
sumber
1
Masuk akal. Tapi kemudian ada pertanyaan mengapa ia tidak menuliskan '.' ketika kamu berlari find *.
nr
@Nr Poin bagus. Saya berharap itu berlaku seperti itu untuk semacam kompatibilitas historis. Saya menambahkan pada jawaban contoh mengapa ini adalah perilaku yang tidak diinginkan.
John1024
3
Beberapa versi file menuntut pengguna untuk memberikan jalur (seperti temuan BSD pada OS X). Jadi Anda biasanya perlu mengatakan sesuatu seperti secara eksplisit find . -type f .... Dari sana, ini bukan langkah besar bagi beberapa versi find (seperti GNU find) untuk default .dan membiarkan semua yang lain apa adanya.
ilkkachu
1
Alasan untuk find *tidak menampilkan .ini adalah karena *mencantumkan semua file dan folder, tetapi tidak termasuk .. Lakukan echo *di direktori yang hanya berisi satu atau dua file, dan Anda akan melihat bahwa .itu tidak terdaftar. Dengan demikian, find *beroperasi pada setiap file yang diperluas. Itu sama seperti jika Anda mengatakan find Desktop/dari direktori home. Anda akan melihat output sebagaiDesktop/foo_bar.txt
Sergiy Kolodyazhnyy
1
@ John1024: Saya percaya bahwa Mrigesh dan Thomas Dickey telah menjawab pertanyaan dengan benar. Jawaban ini menyatakan mengapa nyaman jika findberperilaku seperti itu. Apakah Anda memiliki informasi referensi resmi untuk mendukung klaim tersirat yang finddirancang untuk berperilaku seperti ini karena alasan ini?
G-Man Mengatakan 'Reinstate Monica'
4

The findkebutuhan Jalur perintah (s) untuk mencari. Jika kami tidak menentukan, itu menggunakan direktori saat ini (. ) sebagai titik awal. Demikian pula, jika Anda melewati jalan, misalnya /tmp, itu menganggap itu sebagai titik awal. Dan karenanya hasilnya.

Jika direktori saat ini:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Jika /tmpdirektori:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Jika abcdirektori di bawah direktori saat ini:

        $ find abc

output:
        abc/file6
        abc/file7

Jika banyak direktori di bawah direktori saat ini:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9
Mrigesh Priyadarshi
sumber
Ya, saya setuju findperlu jalur untuk mencari apa pun dan itu default ke direktori saat ini. Pertanyaannya adalah mengapa ia mencetak pemimpin ./ketika file.txtsama saja ./file.txt.
no
1
ini bukan yang ditemukan menambahkan "." di awal sebenarnya ia menambahkan apapun yang Anda berikan sebagai path, apakah itu "/ tmp" "abc" atau ".". Ini akan mengembalikan semua nilai masing-masing.
Mrigesh Priyadarshi
-2

Jika Anda tidak menentukan path, findperintah mengasumsikan ${PWD}sebagai path dan mencetaknya pada outputnya. Pengguna yang tidak menentukan jalur tidak mengubah cara findkerjanya. Dan temukan selalu berfungsi dengan jalur secara default.

MelBurslan
sumber
1
Saya melihat. Tetapi jika Anda jalankan di bawah /tmp, maka $PWDadalah /tmptidak ./.
nr
jika Anda ingin melihat sebelumnya /tmp, jalankan perintah find /tmpJika Anda tidak menentukan path, itu akan selalu menjadi direktori saat ini, yaitu./
MelBurslan
1
Bukannya aku ingin melihat sebelumnya /tmp. Itu tidak mungkin $PWD.
no
${PWD}
Permintaan
2
Tidak, itu tidak menganggap $ PWD. Bandingkan output dari find ., find $PWDdan find(tanpa jalur, jika temuan Anda mendukungnya).
ilkkachu