Làm thế nào để tìm lệnh này bằng cách sử dụng Tìm find -exec sh -c '' '' {{+ + làm việc như thế nào?


8

@StephaneChazelas đã đăng giải pháp sau đây cho câu hỏi và trả lời này: Gặp một số rắc rối khi sử dụng Tìm find -exec {} + .

$ find . -iname "*.extension" -exec sh -c '
  exec <command> "$@" <additional parameters>' sh {} +

Chính xác thì chuyện gì đang xảy ra ở đây vậy? Cụ thể cuối cùng sh {}làm gì? Có vẻ như nó chỉ ở đó để bình định -execlệnh tìm kiếm để nó có việc phải làm, một NOOP.

Tôi có thể dễ dàng đặt echo {}nó ở đó và nó có vẻ hoạt động tốt.

Câu trả lời:


9

Cú pháp là:

find ... -exec cmd {} +

findsẽ tìm thấy một số tệp dựa trên các tiêu chí trong ...và chạy cmdvới danh sách các đường dẫn tệp đó dưới dạng đối số, càng nhiều càng tốt mà không vượt quá giới hạn về kích thước của các đối số cho lệnh.

Nếu cần nó có thể chia danh sách các tập tin và gọi cmdnhiều lần. Ví dụ, nó có thể kết thúc cuộc gọi:

cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321

Một hạn chế với điều đó là {}phải là cuối cùng. Ví dụ, bạn không thể viết:

find ... -exec cmd {} other args +

như bạn có thể với ';'thay vì '+'.

Bạn có thể viết:

find ... -exec echo foo {} +

nhưng không:

find ... -exec echo {} foo +

Vì vậy, nếu bạn cần thêm một số đối số bổ sung vào cmdsau danh sách các tệp, bạn phải dùng đến cách gọi shell. (Những lý do khác khiến bạn cần gọi shell sẽ là bất cứ lúc nào bạn cần sử dụng tính năng shell như chuyển hướng, đường ống, một số mở rộng chuỗi ....)

Trong sh -c 'inline-script' x a b c, đối với inline-script, $0x, $1a, $2b... "$@"danh sách của 3 đối số đó: a, b và c. Vì vậy, trong:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

Đối với tập lệnh nội tuyến , $0(ví dụ được sử dụng khi hiển thị thông báo lỗi) được đặt thành find-sh"$@"là danh sách các tệp (phần findmở rộng {}thành).

Bằng cách sử dụng execnội dung đặc biệt của vỏ:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

Chúng tôi nói với shell không được rẽ nhánh một tiến trình bổ sung để chạy cmd, mà thay vào đó để chạy nó trong cùng một tiến trình (thay thế tiến trình shell đang chạy bằng lệnh đó). Một số vỏ như bash, zshvà một số hiện thực của kshlàm điều đó mặc nhiên cho lệnh cuối cùng trong một kịch bản.


Bạn có thể sử dụng một subshell thay vì exec ở đó? -exec sh -c '(cmd1; cmd2;)' find-sh {} +?
slm

Vì vậy, nếu tôi hiểu bạn một cách chính xác, các find-sh {}đối số của lệnh sh -c '...', phải không?
slm

@slm, findsẽ gọi /bin/shvới các đối số ("sh", "-c", "...", "find-sh", "./file1", "./file2"...). And inside ... , that maps (the shells maps that) to $ 0` "find-sh", và các tham số vị trí ( $1, $2... mà bạn có thể nói là các đối số cho tập lệnh nội tuyến ) đang ./file1, ./file2.
Stéphane Chazelas
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.