2010-06-02 16 views
153

Oggi sono stato aiutato con un comando, ma non sembra funzionare. Questo è il comando:find: argomento mancante per -exec

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

Il guscio ritorna

find: missing argument to `-exec' 

Quello che sto fondamentalmente cercando di fare è passare attraverso una directory ricorsivamente (se ha altre directory) ed eseguire il comando ffmpeg sul .rm tipi di file e convertirli in tipi di file .mp3. Una volta eseguita questa operazione, rimuovere il file .rm appena convertito.

Apprezzo qualsiasi aiuto su questo.

risposta

45

L'ho capito ora. Quando hai bisogno di eseguire due comandi in exec in un find hai bisogno di avere due exec separati. Questo alla fine ha funzionato per me.

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

Non si sa se otterrà la variabile del file da eliminare? Qualcuno sa se questo è il caso? – Abs

+4

Per testare queste cose basta aggiungere un 'echo' prima dei comandi e vedere cosa fa. – Marian

1

Ho bisogno di fare un po 'di fuga, penso.

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

Sia {} e & & causerà problemi dovuti alla fase di espansione dalla linea di comando. Vorrei suggerire cercando:

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

Se il primo comando in exec riesce e il secondo comando in exec viene eseguito, avrà ancora accesso alla variabile '{}' per eliminare il file giusto? – Abs

+0

In che cosa si espande '{}'? A meno che non contenga due punti o virgole che rimarranno come sono. – Marian

258

Un comando -exec deve essere terminata con un ; (modo che di solito bisogno di digitare \; o ';' per evitare interpretion dalla shell) o un +. La differenza è che con ;, il comando viene chiamato una volta per file, con +, viene chiamato solo poche volte (solitamente una volta, ma c'è una lunghezza massima per una riga di comando, quindi potrebbe essere suddiviso) con tutti i nomi di file. Vedere questo esempio:

$ 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 

tuo comando ha due errori:

In primo luogo, si utilizza {};, ma il ; necessario essere un parametro a sé stante.

In secondo luogo, il comando termina allo &&. Hai specificato "Esegui ricerca e, se ciò è successo, rimuovi il file denominato {};". Se si desidera utilizzare la shell nel comando -exec, è necessario eseguirlo esplicitamente in una shell, ad esempio -exec sh -c 'ffmpeg ... && rm'.

Tuttavia, non si dovrebbe aggiungere {} all'interno del comando bash, questo produrrà problemi quando ci sono caratteri speciali. Invece, è possibile passare parametri aggiuntivi per la shell dopo -c command_string (vedi man sh):

$ ls 
$(echo damn.) 
$ find * -exec sh -c 'echo "{}"' \; 
damn. 
$ find * -exec sh -c 'echo "$1"' - {} \; 
$(echo damn.) 

Vedete la cosa $ viene valutata dalla shell nel primo esempio.Immaginate c'era un file chiamato $(rm -rf /) :-)

(Nota a margine: Il - non è necessaria, ma la prima variabile dopo il comando viene assegnato alla variabile $0, che è una variabile speciale normalmente contiene il nome del programma in esecuzione e l'impostazione che a un parametro è un po 'sporca, ma non causerà alcun danno qui, probabilmente, così abbiamo deciso che a poco - e iniziare con $1.)

così il vostro comando potrebbe essere qualcosa di simile

find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \; 

Ma c'è un modo migliore. trovare supporta and e or, quindi è possibile fare cose come find -name foo -or -name bar. Ma funziona anche con -exec, che restituisce true se il comando termina correttamente e false se non lo è. Vedere questo esempio:

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

funziona solo la stampa se il comando fosse successo, che ha fatto per true ma non per false.

Quindi è possibile utilizzare due istruzioni exec concatenate con uno -and e verrà eseguito solo quest'ultimo se il primo è stato eseguito correttamente.

+2

La chiave sembra essere la frase di Marian di "the; is an arg su it's own" che è ciò che ha fatto per me, lightbulb wise e per il mio esempio di codice. Grazie. – pjammer

+1

Questa è la migliore descrizione che ho letto su -exec. È estremamente potente ma trovo sempre difficile ottenere la sintassi corretta per questo. Questo ha reso alcune cose molto più chiare. Involucro speciale del comando nella shell separata. Bello. Grazie. – Eurospoofer

+2

Nota che '-and' e' -or' non sono portatili. [POSIX specifica '-a' e' -o'] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html) e infatti '-a' è sempre assunto (quindi non necessario) . –

35

Prova a mettere uno spazio prima di ogni \;

Works:

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

non funziona:

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

Questo mi fa incazzare abbastanza spesso. Uno di questi giorni, aggiungerò uno spazio per impostazione predefinita. – harperville

+0

Per me funziona esattamente l'opposto in Cygwin sotto Windows 7: senza spazio prima \; funziona, con lo spazio - no. Ma se rimuovo \, con spazio prima; funziona, e senza spazio prima; non lo fa, proprio come descritto qui. – WebComer

7

Per vostra informazione:
ho appena provato con "find -exec" comando su un sistema Cygwin (UNIX emulato su Windows), e sembra che il backslash prima della virgola deve essere rimosso:
find ./ -name "blabla" -exec wc -l {} ;

+0

Sono davvero confuso. 'trova/etc/nginx -name '* .conf' -exec echo {};' e 'trova/etc/nginx -name '* .conf' -exec echo {} \;' ha dato lo stesso risultato. :( – Kirby

+0

Sto eseguendo la shell di Bash che viene fornito con Git per Windows, e la risposta di Dustin Cowles funziona per me. In altre parole: nessuna virgoletta, barra inversa fuori da punto e virgola, spazio dopo '{}'. – mamacdon

2

Nel caso in cui qualcuno vedesse un simile "missing-esec args" negli script di Amazon Opsworks Chef, avevo bisogno di aggiungere un altro backslash per uscire da \;

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

Inoltre, se qualcun altro ha il "trovare: argomento mancante per -exec" questo potrebbe aiutare:

In alcune conchiglie non è necessario per fare la fuga, vale a dire che non è necessario la "\" davanti al ";".

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

Se si sta ancora ricevendo "trovare: argomento mancante per -exec" provare avvolgendo l'argomento eseguire tra virgolette.

find <file path> -type f -exec "chmod 664 {} \;" 
Problemi correlati