Un -exec
comando deve essere terminato con un ;
(quindi di solito è necessario digitare \;
o ';'
per evitare l'interpretazione da parte della shell) o un +
. La differenza è che con ;
, il comando viene chiamato una volta per file, con +
, viene chiamato il minor numero di volte possibile (di solito una volta, ma esiste una lunghezza massima per una riga di comando, quindi potrebbe essere suddiviso) con tutti i nomi di file . Vedi 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
Il tuo comando ha due errori:
In primo luogo, si utilizza {};
, ma ;
deve essere un parametro a sé stante.
In secondo luogo, il comando termina in &&
. Hai specificato "run find, e se ciò ha avuto successo, rimuovi il file chiamato {};
.". Se si desidera utilizzare roba di shell nel -exec
comando, è necessario eseguirla esplicitamente in una shell, ad esempio -exec sh -c 'ffmpeg ... && rm'
.
Comunque non dovresti aggiungere {} all'interno del comando bash, produrrà problemi quando ci sono caratteri speciali. Invece, puoi passare parametri aggiuntivi alla 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.)
Vedi la $
cosa viene valutata dalla shell nel primo esempio. Immagina che ci fosse un file chiamato $(rm -rf /)
:-)
(Nota a margine: -
non è necessario, ma la prima variabile dopo il comando è assegnata alla variabile $0
, che è una variabile speciale che normalmente contiene il nome del programma in esecuzione e l'impostazione su un parametro è un po 'sporca, anche se ha vinto probabilmente causerà qualche danno qui, quindi lo impostiamo su giusto -
e per cominciare $1
.)
Quindi il tuo 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 supporti and
e or
, quindi, puoi fare cose come find -name foo -or -name bar
. Ma funziona anche con -exec
, che valuta vero se il comando termina correttamente e falso in caso contrario. Vedi questo esempio:
$ ls
false true
$ find * -exec {} \; -and -print
true
Esegue la stampa solo se il comando è stato eseguito correttamente, cosa che ha fatto per true
ma non per false
.
Quindi puoi usare due istruzioni exec concatenate con an -and
, e eseguirà quest'ultima solo se la prima è stata eseguita con successo.