2010-06-02 34 views
153

Tôi đã được trợ 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:tìm: thiếu đối số đến -exec

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

Vỏ trả

find: missing argument to `-exec' 

Những gì tôi về cơ bản 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 .rm loại tệp và chuyển đổi chúng thành các loại tệp .mp3. Khi việc này hoàn tất, hãy xóa tệp .rm vừa được chuyển đổi.

Tôi đánh giá cao bất kỳ trợ giúp nào về vấn đề này.

Trả lời

45

Tôi đã tìm ra ngay bây giờ. Khi bạn cần phải chạy hai lệnh trong exec trong một tìm thấy bạn cần phải thực sự có hai execs riêng biệt. Đ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 {} \; 
+0

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

+4

Để 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

1

Bạn cần thực hiện một số thao tác thoát.

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

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

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

Nếu lệnh đầu tiên trong exec thành công và lệnh thứ hai trong exec được thực hiện, nó sẽ vẫn có quyền truy cập vào biến '{}' để xóa tệp phải không? – Abs

+0

Làm thế nào để bạn thinik '{}' mở rộng? Trừ khi nó chứa hai dấu chấm hoặc dấu phẩy sẽ vẫn như cũ. – Marian

258

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ợ andor, 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.

+2

Chìa khóa có vẻ là dòng chữ của Marian "của; là một arg ngày của riêng nó" đó là những gì đã làm nó cho tôi, bóng đèn khôn ngoan và cho mẫu mã của tôi. cảm ơn. – pjammer

+1

Đó là về mô tả tốt nhất tôi đã đọc trên -exec. Nó cực kỳ mạnh mẽ nhưng tôi luôn thấy khó 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 biệt. Tốt đẹp. Cảm ơn. – Eurospoofer

+2

Lưu ý rằng '-and' và' -or' không di động. [POSIX chỉ định '-a' và' -o'] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html) và trên thực tế '-a' luôn được giả định (do đó không cần thiết) . –

35

Thử đặt dấu cách trước mỗi \;

trình:

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

không hoạt động:

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

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

+0

Đối với tôi, nó hoạt động ngược lại với Cygwin trong Windows 7: không có dấu cách trước \; làm việc, với không gian - không. Nhưng nếu tôi xóa \, với dấu cách trước đó; nó hoạt động, và không có không gian trước đó; nó không giống như cách nó được mô tả ở đây. – WebComer

7

Chỉ cần cho thông tin của bạn:
Tôi vừa cố gắng sử dụng "tìm exec" lệnh trên một hệ thống Cygwin (UNIX 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 {} ;

+0

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

+0

Tôi đang chạy vỏ Bash đi kèm với Git cho Windows và câu trả lời của Dustin Cowles có tác dụng đối 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 được thoát bằng dấu chấm phẩy, dấu cách sau '{}'. – mamacdon

2

Chỉ trong trường hợp bất cứ ai nhìn thấy một tương tự "thiếu -exec args" trong Amazon Opsworks đầu bếp bash script, tôi cần thiết để thêm một dấu gạch chéo ngượ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 
3

Ngoài ra, nếu bất cứ ai khác có "tìm: thiếu đối số để exec" này có thể giúp:

Trong một số vỏ bạn không cần phải làm như thoát, tức là bạn không cần "\" ở phía trước ";".

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

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

find <file path> -type f -exec "chmod 664 {} \;" 
Các vấn đề liên quan