Một lệnh -exec
phải được chấm dứt với một ;
(do đó bạn thường cần phải gõ \;
hoặc ';'
để tránh interpretion bằng vỏ) hoặc một +
. Sự khác biệt là với ;
, lệnh được gọi một lần cho mỗi tệp, với +
, lệnh này được gọi ít nhất một lần (thường là một lần, nhưng có độ dài tối đa cho dòng lệnh, vì vậy có thể chia nhỏ) với tất cả các tên tập tin. Xem ví dụ sau:
$ cat /tmp/echoargs
#!/bin/sh
echo $1 - $2 - $3
$ find /tmp/foo -exec /tmp/echoargs {} \;
/tmp/foo - -
/tmp/foo/one - -
/tmp/foo/two - -
$ find /tmp/foo -exec /tmp/echoargs {} +
/tmp/foo - /tmp/foo/one - /tmp/foo/two
lệnh của bạn có hai lỗi:
Trước tiên, bạn sử dụng {};
, nhưng ;
phải là một tham số của riêng nó.
Thứ hai, lệnh kết thúc tại &&
. Bạn đã chỉ định “chạy tìm và nếu thành công, hãy xóa tệp có tên {};
.”. Nếu bạn muốn sử dụng công cụ vỏ trong lệnh -exec
, bạn cần phải chạy nó một cách rõ ràng trong một trình bao, chẳng hạn như -exec sh -c 'ffmpeg ... && rm'
.
Tuy nhiên bạn không nên thêm {} bên trong lệnh bash, nó sẽ tạo ra sự cố khi có các ký tự đặc biệt. Thay vào đó, bạn có thể vượt qua các thông số bổ sung cho vỏ sau -c command_string
(xem man sh
):
$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)
Bạn thấy điều $
được đánh giá bởi các vỏ trong ví dụ đầu tiên.Hãy tưởng tượng có một tệp được gọi là $(rm -rf /)
:-)
(Lưu ý bên: Số -
là không cần thiết, nhưng biến đầu tiên sau khi lệnh được gán cho biến $0
, là biến đặc biệt thường chứa tên chương trình được chạy và cài đặt mà để một tham số là một chút ô uế, mặc dù nó sẽ không gây ra bất kỳ tác hại ở đây có lẽ, vì vậy chúng tôi thiết lập mà chỉ -
và bắt đầu với $1
.)
vì vậy, lệnh của bạn có thể là một cái gì đó giống như
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Nhưng có một cách tốt hơn. tìm hỗ trợ and
và or
, vì vậy bạn có thể thực hiện các công cụ như find -name foo -or -name bar
. Nhưng điều đó cũng làm việc với -exec
, đánh giá thành true nếu lệnh thoát thành công và sai nếu không. Xem ví dụ sau:
$ ls
false true
$ find * -exec {} \; -and -print
true
Nó chỉ chạy in nếu lệnh là thành công, mà nó đã làm cho true
nhưng không phải cho false
.
Vì vậy, bạn có thể sử dụng hai câu lệnh exec bị xích với một -and
và nó sẽ chỉ thực hiện sau nếu lệnh trước đó được chạy thành công.
Bạn không chắc chắn sẽ xóa biến của tệp? Bất cứ ai biết nếu đây là trường hợp? – Abs
Để kiểm tra những điều như vậy chỉ cần thêm một 'echo' trước khi các lệnh và xem những gì nó làm. – Marian