`find` với nhiều` -name` và` -exec` chỉ thực hiện các kết quả khớp cuối cùng của `-name`


74

Khi tôi đang sử dụng

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"

Nó tìm thấy tất cả các loại tập tin. Nhưng khi tôi thêm -execvào cuối:

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt" -exec sh -c 'echo "$0"' {} \;

Có vẻ như nó chỉ in .txtcác tập tin. Tôi đang làm gì sai?

Lưu ý: sử dụng MINGW (Git Bash)


Gợi ý: lệnh đầu tiên cũng sẽ in các thư mục có tên trùng khớp *.js*hoặc *.txt.
tự đại diện

Câu trả lời:


99
tìm thấy . -type f -name "* .htm *" -o -name "* .js *" -o -name "* .txt"

là viết tắt của:

tìm thấy . \ (\ ( -type f -a -name "* .htm *" \) -o \
          \ ( -name "* .js *" \) -o \
          \ ( -name "* .txt" \) \
       \) -Một bản in

Đó là bởi vì không có biến vị ngữ hành động nào được chỉ định (chỉ điều kiện ), nên một -printhành động được thêm vào cho các tệp khớp với các điều kiện.

(và, nhân tiện, điều đó sẽ in các .jstệp không thường xuyên ( -type fchỉ áp dụng cho .htmcác tệp)).

Trong khi:

tìm thấy . -type f -name "* .htm *" -o -name "* .js *" -o -name "* .txt" \
  -exec sh -c 'echo "$ 0"' {} \;

là viết tắt của:

tìm thấy . \ ( -type f -a -name "* .htm *" \) -o \
       \ ( -name "* .js *" \) -o \
       \ ( -name "* .txt" -a -exec sh -c 'echo "$ 0"' {} \; \)

find(như trong nhiều ngôn ngữ), AND ( -a; ẩn khi bị bỏ qua) được ưu tiên hơn OR ( -o) và thêm một vị từ hành động rõ ràng (ở đây -exec) hủy bỏ -printhành động ngầm nhìn thấy ở trên. Ở đây, bạn muốn:

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) \
  -exec sh -c 'echo "$0"' {} \;

Hoặc là:

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c '
   for i do
     echo "$i"
   done' sh {} +

Để tránh chạy một shtệp trên mỗi tệp.


Trong một số sử dụng sh -c đó, bạn cần thêm đối số zeroth cho sh (mặc dù trong các phần khác bạn đã bao gồm nó).
James Youngman

1
Đó là một câu trả lời tuyệt vời!
Marinos An

30

Đây là dấu ngoặc ngụ ý. Thêm dấu ngoặc rõ ràng.\( \)

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c 'echo "$0"' {} \;

hoặc sử dụng xargs (Tôi thích xargs tôi thấy nó dễ dàng hơn, nhưng dường như không phải là di động).

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -print0 | xargs -0 -n1 echo
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.