find -exec: thêm đối số giữa {} và +
Tôi muốn sử dụng find để định vị tệp, sau đó sao chép chúng vào một thư mục, vì vậy tôi đã thử:
find . -name '*.png' -exec cp {} /tmp/dest +
Tuy nhiên, điều này không thành công với
find: missing argument to `-exec'
Khi tôi thay thế +bằng một, ;nó hoạt động, nhưng gọi cp cho từng tệp riêng lẻ. Làm cách nào để thêm đối số theo sau (chẳng hạn như thư mục đích) khi sử dụng +biểu mẫu của -exec?
Tất nhiên, trong trường hợp này, tôi có thể khắc phục hạn chế rõ ràng bằng cách sử dụng cp -t(chẳng hạn như được chỉ ra trong bài đăng này trên Stack Overflow , nhưng giải pháp đó dành riêng cho cp. Thay vào đó, tôi có thể đang sử dụng rsync, scp hoặc một số công cụ khác. Có một cách chung để thêm các đối số giữa {}và +trong find -exec?
Trả lời
Không, nếu bạn đang sử dụng -exec ... {} +, có thể không có gì giữa {}và +ngoài khoảng trắng. Không có cách nào xung quanh điều đó.
Từ đặc điểm kỹ thuật tiêu chuẩn POSIX của các findlệnh :
-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +Phần cuối của biểu thức chính phải được đánh dấu bằng dấu a
<semicolon>hoặc bằng a<plus-sign>. Chỉ một<plus-sign>ngay sau đối số chỉ chứa hai ký tự mới{}được chấm câu ở cuối biểu thức chính. Các mục đích sử dụng khác của<plus-sign>nó sẽ không được coi là đặc biệt.
Một giải pháp chung chung hơn có thể là
find ... -exec sh -c 'cp "$@" /tmp/dest' sh {} +
Ở đây, một sh -ctập lệnh nội tuyến được thực thi với hàng loạt đối số từ find. Bên trong tập lệnh nội tuyến, "$@"sẽ là danh sách các đối số được truyền (được trích dẫn riêng lẻ), cho phép chúng ta đặt chúng theo ý muốn trên cpdòng lệnh.
Điều này cho phép chúng tôi sử dụng không phải GNU cp(ví dụ như macOS hoặc các hệ thống BSD khác, nơi không có -ttùy chọn) hoặc bất kỳ tiện ích nào khác mà người ta có thể muốn thêm các đối số khác vào cuối danh sách tên đường dẫn find.
Có liên quan:
- Hiểu tùy chọn -exec của `find`
Không ai yêu cầu điều này, nhưng dù sao ...
Với mục đích trong một biến, destdir:
destdir=/tmp/dest
find ... -exec sh -c 'destdir=$1; shift; cp "$@" "$destdir"' sh "$destdir" {} +
Lưu ý rằng lệnh destdirgọi trong shell findlà một biến riêng biệt với destdirtrong sh -cscript.
Hoặc, với bash:
destdir=/tmp/dest
find ... -exec bash -c 'cp "${@:2}" "$1"' bash "$destdir" {} +
Đây là "cắt" "$@"danh sách để sắp xếp lại nó một cách thích hợp cho cpdòng lệnh, mà không cần trích xuất $1, tên đường dẫn thư mục đích, thành một biến riêng biệt.