Tại sao tìm thấy in một './' hàng đầu nếu không có đường dẫn nào được đưa ra?


13

Tại sao nó lại findin ra một ./kết quả dẫn đến kết quả nếu không có đường dẫn nào được đưa ra?

$ find
./file1
./file2
./file3

Lý do cho việc không in ra điều này là gì?

$ find
file1
file2
file3

Câu trả lời:


16

Các lý do tại sao bạn thấy điều này là bởi vì các nhà phát triển của GNU chọn để cung cấp một hành vi "hợp lý" cho khi không có đường dẫn được đưa ra. Ngược lại, POSIX không nói rằng tham số là tùy chọn:find find

Các findtiện ích đệ quy sẽ xuống hệ thống phân cấp thư mục từ mỗi tập tin theo quy định của con đường , đánh giá một biểu thức Boolean gồm bầu cử sơ bộ được mô tả trong phần OPERANDS cho mỗi tập tin gặp phải. Mỗi toán hạng đường dẫn sẽ được đánh giá không thay đổi khi được cung cấp, bao gồm tất cả các <slash>ký tự dấu ; tất cả các tên đường dẫn cho các tệp khác gặp phải trong cấu trúc phân cấp sẽ bao gồm nối các toán hạng đường dẫn hiện tại, <slash>nếu toán hạng đường dẫn hiện tại không kết thúc bằng một và tên tệp liên quan đến toán hạng đường dẫn. Phần tương đối sẽ không chứa các thành phần dấu chấm hoặc dấu chấm, không có dấucác ký tự và chỉ các <slash>ký tự đơn giữa các thành phần tên đường dẫn.

Bạn có thể thấy sự khác biệt trong bản tóm tắt cho mỗi. GNU có (theo quy ước) các mục tùy chọn trong ngoặc vuông:

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

trong khi POSIX không chỉ ra rằng nó có thể là tùy chọn:

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

Trong chương trình GNU, điều đó được thực hiện trong ftsfind.c:

  nếu (trống)
    {
      / *
       * Chúng tôi sử dụng một biến tạm thời ở đây vì một số hành động sửa đổi
       * đường dẫn tạm thời. Do đó, nếu chúng ta sử dụng hằng chuỗi
       * chúng tôi nhận được một coredump. Ví dụ tốt nhất về điều này là nếu chúng ta nói
       * "find -printf% H" (lưu ý, không phải "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      trả về tìm (defaultpath);
    }

và một nghĩa đen "."được sử dụng cho đơn giản. Vì vậy, bạn sẽ thấy kết quả tương tự với

find

find .

bởi vì (và POSIX đồng ý) đường dẫn đã cho sẽ được sử dụng để tiền tố kết quả (xem phần trên để nối ).

Với một chút công việc, người ta có thể xác định khi nào tính năng này được thêm lần đầu tiên; nó đã có mặt trong lần đầu tiên tạo ra "findutils" vào năm 1996 (xem 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);
+}

Từ thay đổi cho tìm 3,8, điều này rõ ràng là

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 "."

11

Thông thường, người ta xử lý hậu kỳ các tệp và trong trường hợp đó, có thể có một lợi thế rất lớn để bắt đầu tên tệp ./. Cụ thể, nếu một tên tệp bắt đầu bằng -, một lệnh tiếp theo có thể diễn giải tên tệp đó là một tùy chọn. ./tránh điều đó

Ví dụ, xem xét một thư mục với các tệp này:

$ ls
--link  --no-clobber

Bây giờ, hãy tưởng tượng lệnh này sẽ hoạt động như thế nào nếu tên tệp được cung cấp mà không có ./phía trước:

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

Chúng ta có thể minh họa vấn đề với findchính nó. Hãy chạy nó trong cùng thư mục như trên. Các công việc sau đây:

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

Lỗi sau:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.

1
Nó có ý nghĩa. Nhưng sau đó có câu hỏi tại sao nó không trả trước một '.' khi bạn chạy find *.
nr

@nr Điểm tốt. Tôi hy vọng rằng nó hành xử theo cách đó cho một số loại tương thích lịch sử. Tôi đã thêm vào câu trả lời một ví dụ về lý do tại sao đây là hành vi không mong muốn.
John1024

3
Một số phiên bản file yêu cầu người dùng đưa ra một đường dẫn (như tìm thấy BSD trên OS X). Vì vậy, bạn thường cần phải nói rõ ràng một cái gì đó như find . -type f .... Từ đó, không phải là một bước tiến lớn đối với một số phiên bản tìm kiếm (như GNU find) chỉ mặc định .và để mọi thứ khác như hiện tại.
ilkkachu

1
Lý do find *không hiển thị .là vì *liệt kê tất cả các tệp và thư mục, nhưng loại trừ .. Làm echo *trong một thư mục chỉ chứa một hoặc hai tệp và bạn sẽ thấy nó .không được liệt kê. Do đó, find *hoạt động trên mỗi tập tin mở rộng. Nó giống như bạn nói find Desktop/từ thư mục nhà. Bạn sẽ thấy đầu ra làDesktop/foo_bar.txt
Sergiy Kolodyazhnyy

1
@ John1024: Tôi tin rằng MrigeshThomas Dickey đã trả lời đúng câu hỏi. Câu trả lời này cho biết tại sao nó thuận tiện mà findhành xử theo cách của nó. Bạn có bất kỳ thông tin tham khảo có thẩm quyền để hỗ trợ cho yêu cầu ngụ ý findđược thiết kế để hành xử theo cách này vì lý do này?
G-Man nói 'Phục hồi Monica'

4

Các findnhu cầu lệnh đường dẫn (s) để tìm kiếm. Nếu chúng tôi không chỉ định bất kỳ, nó sử dụng thư mục hiện tại ( .) làm điểm bắt đầu. Tương tự, nếu bạn vượt qua đường dẫn, ví dụ /tmp, nó coi đó là điểm bắt đầu. Và do đó, kết quả.

Nếu thư mục hiện tại:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Nếu /tmpthư mục:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Nếu abcthư mục trong thư mục hiện tại:

        $ find abc

output:
        abc/file6
        abc/file7

Nếu nhiều thư mục trong thư mục hiện tại:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9

Vâng tôi đồng ý find cần một đường dẫn để tìm kiếm bất cứ thứ gì và nó mặc định là thư mục hiện tại. Câu hỏi là tại sao nó in ra hàng đầu ./khi file.txtchỉ giống như ./file.txt.
nr

1
Nó không tìm thấy thêm "." khi bắt đầu, nó thực sự bổ sung bất cứ thứ gì bạn cung cấp cho nó dưới dạng đường dẫn, cho dù đó là "/ tmp" "abc" hay ".". Nó sẽ trả về tất cả các giá trị tương ứng.
Mrigesh Priyadarshi

-2

Nếu bạn không chỉ định một đường dẫn, findlệnh sẽ giả sử ${PWD}là đường dẫn và in nó ra trên đầu ra của nó. Người dùng không chỉ định đường dẫn không thay đổi cách findlàm việc. Và tìm luôn hoạt động với các đường dẫn theo mặc định.


1
Tôi hiểu rồi. Nhưng nếu bạn thực hiện nó dưới /tmp, sau đó $PWD/tmpkhông ./.
nr

nếu bạn muốn xem trước /tmp, hãy chạy lệnh find /tmpNếu bạn không chỉ định đường dẫn, nó sẽ luôn là thư mục hiện tại, đó là./
MelBurslan

1
Không phải là tôi muốn xem trước /tmp. Đó là nó không thể $PWD.
nr

Lời xin lỗi của tôi ${PWD}là thông báo không chính xác
MelBurslan

2
Không, nó không giả định $ PWD. Hãy so sánh sản lượng find ., find $PWDfind(không có một con đường, nếu tìm bạn hỗ trợ nó).
ilkkachu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.