Sử dụng kết nối sau khi tìm lệnh


10

Tôi muốn bash của tôi chỉ in 'tìm thấy' nếu tìm thấy thứ gì đó, sử dụng lệnh find. Nhưng sử dụng && không giúp ích gì: ngay cả khi không tìm thấy gì, tôi vẫn nhận được 'tìm thấy'. Thí dụ:

$ pwd
/data/data/com.termux/files/home/test/test1/test4
$ ls
xaa  xab
$ find . -name xac && echo 'found'
found
$ find . -name xaa && echo 'found'
./xaa
found

Câu trả lời:


18

Bạn có thể findtự in found:

find . -name xac -printf "found\n" -quit

Các -quitsẽ làm cho find từ chức sau khi trận đấu đầu tiên , vì vậy foundchỉ được in tối đa một lần.

Trên một luồng tương tự trên Unix & Linux ( tìm kiếm thất bại khi không tìm thấy gì ), tôi đã sử dụng grep -qzđể trả về trạng thái thoát khác không nếu findkhông tìm thấy gì:

find /some/path -print0 -quit | grep -qz .

Mà bạn có thể sử dụng để xây dựng các lệnh ghép bằng &&hoặc if:

find /some/path -print0 -quit | grep -qz . && echo found

Tôi phải nhìn chằm chằm vào một lúc /some/pathnó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ì đó?
Joe

@Joe điều quan trọng ở đây là -print0 -quit. Những gì bạn đặt trước đó phụ thuộc vào những gì bạn muốn tìm. Tôi đã chọn bỏ qua điều đó ở đây.
muru

13

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 -execcờ.

$ 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\;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 findlệ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 thatsắp xếp, chúng ta có thể sử dụng lệnh biến áp $()testlệ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 varvà nó có chứa hello worldvăn bản, khi bạn làm touch $varvỏ sẽ phá vỡ nó xuống thành hai hạng mục riêng biệt helloworldtouchsẽ 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 worldlà một đơn vị và touchsẽ 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, findkhông bị hành vi như vậy, bởi vì các lệnh được xử lý bởi findchí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 findlệ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 statlệ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, statnhậ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

Sẽ không echo "I found {}"tốt hơn echo "I found " {}? 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 đề.
Dan

@Dan chủ đề quá dài để thảo luận trong các bình luận, vì vậy tôi đã chỉnh sửa câu trả lời của mình. Xin vui lòng xem nó
Sergiy Kolodyazhnyy

1
Cảm ơn vì cuối cùng đã cho tôi hiểu lý do tại sao dấu chấm phẩy đó cần ở đó. Ngoài ra, giải thích tuyệt vời của trích dẫn.
Joe

1
Không mong đợi nhiều chi tiết như một câu trả lời cho nhận xét của tôi. Tôi rất đánh giá cao lời giải thích đó, cảm ơn!
Dan
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.