Ein -exec
Befehl muss mit a ;
(daher müssen Sie normalerweise eingeben \;
oder ';'
eine Interpretation durch die Shell vermeiden) oder a beendet werden +
. Der Unterschied besteht darin, dass mit ;
der Befehl mit einmal pro Datei aufgerufen wird. Mit wird der Befehl +
mit allen Dateinamen so oft wie möglich aufgerufen (normalerweise einmal, aber es gibt eine maximale Länge für eine Befehlszeile, sodass sie möglicherweise aufgeteilt wird) . Siehe dieses Beispiel:
$ 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
Ihr Befehl hat zwei Fehler:
Zuerst verwenden Sie {};
, aber das ;
muss ein eigener Parameter sein.
Zweitens endet der Befehl am &&
. Sie haben "find ausführen" ausgeführt. Wenn dies erfolgreich war, entfernen Sie die Datei mit dem Namen {};
. Wenn Sie Shell-Inhalte im -exec
Befehl verwenden möchten , müssen Sie sie explizit in einer Shell ausführen, z -exec sh -c 'ffmpeg ... && rm'
.
Sie sollten das {} jedoch nicht in den Befehl bash einfügen, da dies zu Problemen führen kann, wenn Sonderzeichen vorhanden sind. Stattdessen können Sie nach -c command_string
(siehe man sh
) zusätzliche Parameter an die Shell übergeben :
$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)
Sie sehen, dass das $
Ding im ersten Beispiel von der Shell ausgewertet wird. Stellen Sie sich vor, es gäbe eine Datei namens $(rm -rf /)
:-)
(Randnotiz: Die -
wird nicht benötigt, aber die erste Variable nach dem Befehl wird der Variablen zugewiesen. Hierbei handelt $0
es sich um eine spezielle Variable, die normalerweise den Namen des ausgeführten Programms enthält. Die Einstellung auf einen Parameter ist etwas unrein, obwohl sie gewonnen hat wird hier wahrscheinlich keinen Schaden anrichten, also setzen wir das auf gerecht -
und beginnen mit $1
.)
Ihr Befehl könnte also so etwas wie sein
find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Aber es gibt einen besseren Weg. Finden Sie Unterstützung and
und or
, so können Sie Dinge wie tun find -name foo -or -name bar
. Das funktioniert aber auch mit -exec
, was als wahr ausgewertet wird, wenn der Befehl erfolgreich beendet wird, und als falsch, wenn nicht. Siehe dieses Beispiel:
$ ls
false true
$ find * -exec {} \; -and -print
true
Der Druck wird nur ausgeführt, wenn der Befehl erfolgreich war, wofür er ausgeführt wurde, true
jedoch nicht false
.
Sie können also zwei exec-Anweisungen verwenden, die mit a verkettet sind -and
, und letztere werden nur ausgeführt, wenn erstere erfolgreich ausgeführt wurden.