tìm: thiếu đối số cho -exec


206

Tôi đã được giúp đỡ hôm nay với một lệnh, nhưng nó dường như không hoạt động. Đây là lệnh:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;

Vỏ trả về

find: missing argument to `-exec'

Những gì tôi về cơ bản đang cố gắng làm là đi qua một thư mục đệ quy (nếu nó có các thư mục khác) và chạy lệnh ffmpeg trên các .rmloại tệp và chuyển đổi chúng thành .mp3các loại tệp. Một khi điều này được thực hiện, loại bỏ các .rmtập tin vừa được chuyển đổi.

Tôi đánh giá cao bất kỳ sự giúp đỡ về điều này.

Câu trả lời:


340

Một -execlệnh phải được chấm dứt bằng một ;(vì vậy bạn thường cần phải gõ \;hoặc ';'để tránh sự diễn giải bằng vỏ) hoặc a +. Sự khác biệt là với ;lệnh được gọi một lần cho mỗi tệp, với +, nó được gọi càng ít lần càng tốt (thường là một lần, nhưng có độ dài tối đa cho một dòng lệnh, vì vậy nó có thể được tách ra) với tất cả tên tệp . Xem ví dụ này:

$ 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:

Đầu 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 run find 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 shell shell trong -execlệnh, bạn cần chạy nó một cách rõ ràng trong shell, 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 vấn đề 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 shell trong ví dụ đầu tiên. Hãy tưởng tượng có một tập tin gọi là $(rm -rf /):-)

(Lưu ý bên: -Không cần thiết, nhưng biến đầu tiên sau khi lệnh được gán cho biến $0, đây là biến đặc biệt thường chứa tên của chương trình đang chạy và đặt tham số đó là một ô uế, mặc dù nó đã thắng Có thể không gây ra bất kỳ tác hại nào ở đây, vì vậy chúng tôi đặt nó thành -và bắt đầu với $1.)

Vì vậy, lệnh của bạn có thể là một cái gì đó 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ợ andor, vì vậy bạn có thể làm những thứ như find -name foo -or -name bar. Nhưng điều đó cũng hoạt động với -exec, đánh giá là đúng nếu lệnh thoát thành công và sai nếu không. Xem ví dụ này:

$ ls
false  true
$ find * -exec {} \; -and -print
true

Nó chỉ chạy bản in nếu lệnh thành công, nó đã làm truenhưng không làm false.

Vì vậy, bạn có thể sử dụng hai câu lệnh exec được xâu chuỗi với một -andvà nó sẽ chỉ thực hiện câu lệnh sau nếu câu lệnh trước được chạy thành công.


3
Chìa khóa dường như là dòng "the; is a own own" của Marian, đó là những gì đã làm cho tôi, bóng đèn thông minh và cho mẫu mã của tôi. cảm ơn.
pjammer

3
Đó là về mô tả tốt nhất mà tôi đã đọc trên -exec. Nó cực kỳ mạnh mẽ nhưng tôi luôn cảm thấy khó khăn để có được cú pháp đúng cho nó. Điều này làm cho một vài điều rõ ràng hơn nhiều. Đặc biệt gói lệnh trong vỏ riêng. Đẹp. Cảm ơn.
Eurospophone

3
Lưu ý rằng -and-orkhông phải là di động. POSIX chỉ định -a-o , trên thực tế -aluôn được giả định (do đó không cần thiết).
gniourf_gniourf

Ngoài ra phải có một không gian trước khi kết thúc. Ex "\;"không hoạt động nhưng " \;"không
frmdstryr

56

Tôi đã tìm ra nó bây giờ. Khi bạn cần chạy hai lệnh trong exec trong một find, bạn thực sự cần phải có hai exec. Điều này cuối cùng đã làm việc cho tôi.

find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;

Không chắc chắn nếu nó sẽ nhận được các biến của tập tin để xóa? Bất cứ ai biết nếu đây là trường hợp?
abs

7
Để kiểm tra những thứ như vậy, chỉ cần thêm một echotrước các lệnh và xem những gì nó làm.
Mary

2
@Marian, echokhá không đáng tin cậy - bạn không thể phân biệt sự khác biệt giữa echo "one argument"echo one argument(đầu ra của cái sau là sai, vì nó thực sự vượt qua echohai đối số hoàn toàn riêng biệt). Tốt hơn nhiều để làm một cái gì đó như -exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n', nó sẽ in đầu ra theo cách làm cho các ký tự không thể in được hiển thị để bạn có thể phát hiện các dòng mới của DOS và các điều kỳ lạ khác.
Charles Duffy

52

Hãy thử đặt một khoảng trắng trước mỗi \;

Làm:

find . -name "*.log" -exec echo {} \;

Không hoạt động:

find . -name "*.log" -exec echo {}\;

1
Điều này làm tôi đi lên khá thường xuyên. Một trong những ngày này, tôi sẽ thêm một khoảng trắng theo mặc định.
harperville

Đối với tôi, nó hoạt động ngược lại với Cygwin trong Windows 7: không có khoảng trắng trước \; hoạt động, với không gian - không. Nhưng nếu tôi loại bỏ \, với không gian trước đó; nó hoạt động, và không có không gian trước đó; Nó không, chỉ là cách nó được mô tả ở đây.
WebCome

7

Chỉ để biết thông tin của bạn:
Tôi vừa thử sử dụng lệnh "find -exec" trên hệ thống Cygwin (UNIX được mô phỏng trên Windows) và có vẻ như dấu gạch chéo ngược trước dấu chấm phẩy phải được xóa:
find ./ -name "blabla" -exec wc -l {} ;


Tôi thực sự bối rối. find /etc/nginx -name '*.conf' -exec echo {} ;find /etc/nginx -name '*.conf' -exec echo {}\;đưa ra kết quả tương tự. :(
Kirby

Tôi đang chạy shell Bash đi kèm với Git cho Windows và câu trả lời của Dustin Cowles phù hợp với tôi. Nói cách khác: không có dấu ngoặc kép, dấu gạch chéo ngược thoát bằng dấu chấm phẩy, dấu cách sau {}.
mamacdon

Không có sự khác biệt về ý nghĩa, nhưng trong một số trường hợp, bạn cần đặt dấu gạch chéo ngược, trong một số trường hợp bạn không thể đặt nó và trong các trường hợp khác bạn có thể chọn.
Dominique

2

Chỉ trong trường hợp bất kỳ ai nhìn thấy một "đối số -exec bị thiếu" tương tự trong các tập lệnh bash Amazon Opsworks Chef, tôi cần thêm một dấu gạch chéo ngược khác để thoát khỏi \;

bash 'remove_wars' do
  user 'ubuntu'
  cwd '/'
  code <<-EOH
    find /home/ubuntu/wars -type f -name "*.war" -exec rm {} \\;
  EOH
  ignore_failure true
end

2

Ngoài ra, nếu bất kỳ ai khác có "find: thiếu đối số thành -exec" thì điều này có thể giúp:

Trong một số shell bạn không cần thực hiện thoát, tức là bạn không cần "\" phía trước ";".

find <file path> -name "myFile.*" -exec rm - f {} ;

2
Việc ;không được trích dẫn hoặc thoát ra ở đây có nghĩa là nó có thể được tiêu thụ bởi vỏ, không được đọc bởi find. Ngoài ra, -f- flà hai điều khác nhau.
Charles Duffy

1

Bạn cần phải làm một số thoát tôi nghĩ.

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} \-sameq {}.mp3 \&\& rm {}\;

0

Cả {} và && sẽ gây ra sự cố do được mở rộng bởi dòng lệnh. Tôi sẽ đề nghị thử:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i \{} -sameq \{}.mp3 \; -exec rm \{} \;

Nếu lệnh đầu tiên trong exec thành công và lệnh thứ hai trong exec được thực thi, nó vẫn có quyền truy cập vào {}biến để xóa đúng tệp chứ?
Vắng

Bạn thinik {}mở rộng để làm gì? Trừ khi nó chứa hai dấu chấm hoặc dấu phẩy sẽ vẫn như cũ.
Mary

0

Bạn phải đặt một khoảng trống giữa {}\;

Vì vậy, lệnh sẽ như sau:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {} \;

-4

Nếu bạn vẫn nhận được "find: thiếu đối số thành -exec", hãy thử bọc đối số thực thi trong dấu ngoặc kép.

find <file path> -type f -exec "chmod 664 {} \;"
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.