tìm không đệ quy khi tập tin ở đầu


8

Hãy tưởng tượng một cây nguồn. Có tập tin xml ở khắp mọi nơi.

Nhưng vì có một XYZ.xml ở gốc của cây này nên nó sẽ không tìm thấy các tệp xml của tôi.

find -iname *.xml

trả lại

./XYZ.xml

thay vì

./XYZ.xml
./a/b/c/bob.xml
./b/d/top.xml

1
Từ man find: Xin lưu ý rằng bạn nên trích dẫn các mẫu như một vấn đề tất nhiên, nếu không, trình bao sẽ mở rộng bất kỳ ký tự đại diện nào trong chúng.
artdanil

Câu trả lời:


18
find -iname '*.xml'

Mặt khác, shell của bạn mở rộng *.xmlthành XYZ.xmlvà lệnh thực sự được thực thi là

find -iname XYZ.xml

Lý do nó hoạt động nếu không có tệp XML trong thư mục hiện tại là vì các shell thường để các ký tự đại diện chưa được mở rộng nếu chúng không khớp với bất cứ thứ gì. Nói chung, bất cứ lúc nào bạn muốn ký tự đại diện để được mở rộng bằng một chương trình khác hơn so với vỏ (ví dụ bằng find, tar, scp, vv), bạn cần phải trích dẫn họ để vỏ sẽ không cố gắng để mở rộng chúng riêng của mình.


1
Thx, điều đó thật đơn giản, nhưng tôi đã tự hỏi làm thế nào để vượt qua điều đó trong nhiều tháng. Tôi thấy điều đó thực sự kỳ lạ, và là một hành vi rất không nhất quán, nhưng bây giờ tôi hiểu vì nó không tìm thấy, mà là lỗi của bash.
Olivier Toupin

2
Đó không phải là "lỗi" của bash mà là của bạn vì đã không trích dẫn các ký tự đại diện mà bạn muốn chuyển qua làm đối số. Điều này áp dụng cho tất cả các chương trình chấp nhận đầu vào shell. Vỏ mở rộng chúng như những khối u trừ khi chúng được trích dẫn hoặc thoát ra.
Caleb

1
Tôi đoán Olivier có nghĩa như vậy, rằng đó là một vấn đề bashchứ không phải của find.
người dùng không xác định

6

Bạn cần trích dẫn lập luận của bạn như thế này:

find ./ -name '*.xml'

để nó được chuyển qua để tìm thay vì được mở rộng bằng shell, sau đó được chuyển qua để tìm làm phiên bản mở rộng.


1
Ok, vì vậy nếu *.xmlkhông khớp với bất cứ thứ gì trong thư mục hiện tại, nó được truyền theo nghĩa đen, đó là lý do tại sao nó hoạt động trong trường hợp khác. Câu trả lời rất hữu ích.
Eric Wilson

1

Ký tự đại diện được mở rộng bằng vỏ chứ không phải bằng lệnh. findlà một trong số ít các lệnh thực hiện khớp ký tự đại diện tương tự như shell, trong thời gian riêng của nó.

Khi bạn chạy ls *.xml, đầu tiên shell sẽ mở rộng ra *.xmldanh sách các tệp phù hợp, ví dụ file1.xml file2.xml file3.xml, sau đó shell gọi lsvới danh sách các đối số kết quả file1.xml file2.xml file3.xml. Đó là lý do tại sao bạn thấy cùng một danh sách tên tệp echo *.xml, mặc dù echokhông biết gì về tệp và không quan tâm liệu đối số của nó có phải là tên tệp hay không.

Khi bạn chạy find . -name "*.xml":

  1. Shell phân tích cú pháp dòng lệnh để nhận ra các ký tự đặc biệt và chia nó thành các từ và puntination. Ở đây có chỉ là một danh sách các từ find, ., -name, *.xmlnơi *được trích dẫn. Vì *được trích dẫn, nó là một nhân vật bình thường khi có liên quan đến cái vỏ.
  2. Vỏ chạy lệnh findvới danh sách cụ thể các đối số: ., -name, *.xml.
  3. findtìm kiếm các tệp có tên khớp với mẫu *.xmltrong bất kỳ thư mục nào trong thư mục hiện tại.

Khi bạn chạy find . -name *.xmlvà không có tệp nào khớp *.xml:

  1. Shell phân tích cú pháp dòng lệnh để nhận ra các ký tự đặc biệt và chia nó thành các từ và puntination. Ở đây có chỉ là một danh sách các từ find, ., -name, *.xmlnơi *không được trích dẫn.
  2. Vì từ *.xmlnày chứa ký tự đại diện không được trích dẫn, shell thực hiện việc tạo tên tệp. Vì không có tên tệp phù hợp, mẫu vẫn chưa được mở rộng.
  3. Vỏ chạy lệnh findvới kết quả là danh sách các đối số, đó là ., -name, *.xml.
  4. findtìm kiếm các tệp có tên khớp với mẫu *.xmltrong bất kỳ thư mục nào trong thư mục hiện tại.

Khi bạn chạy find . -name *.xmlvà thư mục hiện tại chứa file1.xml, file2.xmlfile3.xml:

  1. Shell phân tích cú pháp dòng lệnh để nhận ra các ký tự đặc biệt và chia nó thành các từ và puntination. Ở đây có chỉ là một danh sách các từ find, ., -name, *.xmlnơi *không được trích dẫn.
  2. Vì từ *.xmlchứa ký tự đại diện không được trích dẫn, shell thực hiện việc tạo tên tệp: *.xmlđược thay thế bằng danh sách các tên tệp phù hợp.
  3. Vỏ chạy lệnh findvới kết quả là danh sách các đối số, đó là ., -name, file1.xml, file2.xml, file3.xml.
  4. findphàn nàn về một lỗi cú pháp khi nó đạt đến file2.xml.

Khi bạn chạy find . -name *.xmlvà thư mục hiện tại chứa một tệp phù hợp file.xml:

  1. Shell phân tích cú pháp dòng lệnh để nhận ra các ký tự đặc biệt và chia nó thành các từ và puntination. Ở đây có chỉ là một danh sách các từ find, ., -name, *.xmlnơi *không được trích dẫn.
  2. Vì từ *.xmlchứa ký tự đại diện không được trích dẫn, shell thực hiện việc tạo tên tệp: *.xmlđược thay thế bằng danh sách các tên tệp phù hợp.
  3. Vỏ chạy lệnh findvới kết quả là danh sách các đối số, đó là ., -name, file.xml.
  4. findthấy một lệnh hoàn toàn hợp lệ, nhưng nó có thể không phải là những gì bạn dự định: findđược yêu cầu tìm các tệp được gọi file.xmltrong bất kỳ thư mục nào, không tìm kiếm bất kỳ tệp nào khớp *.xml.

(Đánh giá và mở rộng Shell có rất nhiều tính năng khác. Tôi chỉ đề cập đến những tính năng có liên quan ở đây.)

(Những gì tôi mô tả là hành vi mặc định của hầu hết các shell phổ biến: sh, bash, dash, ksh,. danh sách. Không ai trong số họ sẽ giúp ở đây.)


-1

Điều này hoạt động trên Solaris 10:

find /directory-to-search/* -prune -name "*gz"


Điều này sẽ không tìm kiếm tên kết thúc bằng .xml.
Kusalananda

-2

Vui lòng thử:

find ./ -name *.xml

Tôi vừa thử điều đó, kết quả tương tự.
Eric Wilson

Tôi đã thử nó, và nó hoạt động. Trên GNU bash 4.2.8
bbaja42

3
Điều này không hoạt động khi toàn cầu khớp với bất cứ thứ gì trong thư mục hiện tại. Đó là cú pháp sai! Các *luôn nên được trích dẫn hoặc thoát để vượt qua nó để tìm.
Caleb
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.