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.
-and
und-or
nicht tragbar sind. POSIX spezifiziert-a
und-o
wird tatsächlich-a
immer angenommen (daher nicht benötigt)."\;"
funktioniert nicht, aber" \;"
funktioniertIch habe es jetzt herausgefunden. Wenn Sie zwei Befehle in exec in einem Find ausführen müssen, müssen Sie tatsächlich zwei separate Execs haben. Das hat endlich bei mir funktioniert.
quelle
echo
vor den Befehlen ein hinzu und sehen Sie, was es tut.echo
ist ziemlich unzuverlässig - man kann den Unterschied zwischenecho "one argument"
und nicht erkennenecho one argument
(dessen Ausgabe ist falsch, da sie tatsächlichecho
zwei völlig getrennte Argumente übergibt ). Es ist viel besser, so etwas zu tun-exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n'
, bei dem die Ausgabe so gedruckt wird, dass nicht druckbare Zeichen sichtbar werden, sodass Sie DOS-Zeilenumbrüche und andere Kuriositäten erkennen können.Versuchen Sie, vor jedem \ ein Leerzeichen zu setzen.
Werke:
Funktioniert nicht:
quelle
Nur zu Ihrer Information:
Ich habe gerade versucht, den Befehl "find -exec" auf einem Cygwin-System (UNIX unter Windows emuliert) zu verwenden, und dort scheint es, dass der Backslash vor dem Semikolon entfernt werden muss:
find ./ -name "blabla" -exec wc -l {} ;
quelle
find /etc/nginx -name '*.conf' -exec echo {} ;
undfind /etc/nginx -name '*.conf' -exec echo {}\;
gab das gleiche Ergebnis. :({}
.Nur für den Fall, dass jemand in Amazon Opsworks Chef-Bash-Skripten ähnliche "fehlende -exec-Argumente" sieht, musste ich einen weiteren Backslash hinzufügen, um dem \ zu entkommen.
quelle
Wenn jemand anderes das "find: fehlende Argument für -exec" hat, kann dies auch helfen:
In einigen Muscheln müssen Sie nicht entkommen, dh Sie brauchen nicht das "\" vor dem ";".
quelle
;
nicht zitierte oder entkommene bedeutet, dass es von der Shell konsumiert und nicht von gelesen werden kannfind
. Auch-f
und- f
sind zwei verschiedene Dinge.Du musst ein bisschen fliehen, denke ich.
quelle
Sowohl {} als auch && verursachen Probleme, da sie über die Befehlszeile erweitert werden. Ich würde vorschlagen, es zu versuchen:
quelle
{}
Variable, um die richtige Datei zu löschen?{}
erweitert Thinik ? Es sei denn, es enthält zwei Punkte oder Kommas, die so bleiben, wie sie sind.Sie müssen ein Leerzeichen zwischen
{}
und setzen\;
Der Befehl lautet also wie folgt:
quelle
Wenn Sie immer noch "find: fehlendes Argument für -exec" erhalten, versuchen Sie, das Argument execute in Anführungszeichen zu setzen.
quelle