Câu trả lời của muru là phù hợp và rất phù hợp cho các trường hợp chúng tôi muốn in một cái gì đó nếu tìm thấy tập tin. Đối với trường hợp chung khi chúng ta muốn thực thi lệnh bên ngoài, chẳng hạn như echo
, chúng ta có thể sử dụng -exec
cờ.
$ find . -name 'xac' -exec echo "I found " {} \; -quit
I found ./xac
Phần {}
truyền tên tệp cho lệnh giữa -exec
và \;
dưới dạng đối số. Lưu ý \
trước ;
- nó ngăn shell hiểu sai trong dấu chấm phẩy đóng vỏ biểu thị kết thúc lệnh, nhưng khi thoát bằng dấu gạch chéo, shell sẽ coi nó là văn bản văn bản được truyền cho find
lệnh và để tìm lệnh nó đóng vai trò là -exec
đối số của cờ đóng .
Để xây dựng các điều kiện if found do this; else do that
sắp xếp, chúng ta có thể sử dụng lệnh biến áp $()
và test
lệnh (aka [
):
$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"
not found
$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"
found
Phát biểu ý kiến của Dan
Dan trong các ý kiến hỏi:
Sẽ không lặp lại "Tôi đã tìm thấy {}" tốt hơn tiếng vang "Tôi đã tìm thấy" {}? Có thể đối với tiếng vang thì không sao, nhưng nếu ai đó sao chép lệnh và thay thế tiếng vang bằng lệnh khác, họ có thể gặp vấn đề
Trước tiên hãy hiểu vấn đề. Thông thường, trong shell có khái niệm phân tách từ, có nghĩa là các biến không được trích dẫn và các tham số vị trí sẽ được mở rộng và được coi là các mục riêng biệt. Ví dụ, nếu bạn có biến var
và nó có chứa hello world
văn bản, khi bạn làm touch $var
vỏ sẽ phá vỡ nó xuống thành hai hạng mục riêng biệt hello
và world
và touch
sẽ hiểu rằng như thể bạn đang cố gắng để tạo ra 2 file riêng biệt; nếu bạn làm như vậy touch "$var"
thì shell sẽ coi hello world
là một đơn vị và touch
sẽ chỉ tạo một tệp. Điều này rất quan trọng để hiểu rằng điều này chỉ xảy ra do cách thức hoạt động của đạn pháo.
Ngược lại, find
không bị hành vi như vậy, bởi vì các lệnh được xử lý bởi find
chính nó và được thực thi bằng execvp()
lệnh gọi hệ thống, do đó không có vỏ liên quan. Trong khi các dấu ngoặc nhọn có ý nghĩa đặc biệt trong các shell, bởi vì chúng xuất hiện ở giữa find
lệnh và không phải lúc đầu, chúng không mang ý nghĩa đặc biệt nào đối với shell trong trường hợp này. Đây là một ví dụ. Chúng ta hãy tạo một vài tên tệp khó và cố gắng chuyển chúng thành đối số để ra stat
lệnh.
$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt
$ find -type f -exec stat -c "%F" {} \; -print
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt
Như bạn có thể thấy, stat
nhận được tên tệp khó hoàn toàn tốt find
, đó là một trong những lý do chính tại sao nên sử dụng tập lệnh di động và đặc biệt hữu ích khi bạn duyệt qua cây thư mục và muốn làm gì đó với tên tệp có khả năng có nhân vật đặc biệt trong họ. Do đó, không cần thiết phải trích dẫn dấu ngoặc nhọn cho các lệnh được thực thi find
.
Đó là một câu chuyện khác nhau khi vỏ được tham gia. Đôi khi bạn cần sử dụng shell để xử lý tên tệp. Trong trường hợp đó, trích dẫn sẽ thực sự quan trọng, nhưng điều quan trọng là phải nhận ra rằng đó không phải là vấn đề - đó là cái vỏ tách từ.
$ find -type f -exec bash -c "stat {}" sh \;
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory
Vì vậy, khi chúng tôi trích dẫn trong shell , nó sẽ hoạt động. Nhưng một lần nữa, điều đó quan trọng đối với vỏ, không find
.
$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;
regular empty file
regular empty file
regular empty file
/some/path
nói tìm nơi để bắt đầu tìm kiếm, nhưng không có gì cho nó biết những gì cần tìm. Tương tự trong câu trả lời liên kết của bạn. Những gì làm việc cho tôi làfind /some/path -name xac -print0 -quit | grep -qz . && echo found
. Tôi đã bỏ lỡ một cái gì đó?