Ich möchte genau wissen, was {} \;
und {} \+
und | xargs ...
. Bitte klären Sie diese mit Erläuterungen.
Unter 3 Befehlen wird das gleiche Ergebnis ausgeführt und ausgegeben, aber der erste Befehl benötigt etwas Zeit und das Format unterscheidet sich ebenfalls geringfügig.
find . -type f -exec file {} \;
find . -type f -exec file {} \+
find . -type f | xargs file
Dies liegt daran, dass der erste file
Befehl für jede Datei ausgeführt wird, die vom find
Befehl stammt. Im Grunde läuft es also wie folgt:
file file1.txt
file file2.txt
Aber letztere 2 finden mit -exec
Befehlen den Befehl file einmal für alle Dateien wie unten ausführen:
file file1.txt file2.txt
Dann führe ich die folgenden Befehle aus, bei denen der erste ohne Probleme ausgeführt wird, der zweite jedoch eine Fehlermeldung ausgibt.
find . -type f -iname '*.cpp' -exec mv {} ./test/ \;
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+ #gives error:find: missing argument to `-exec'
Für Befehl mit {} \+
gibt es mir die Fehlermeldung
find: missing argument to `-exec'
warum ist das so? Kann mir bitte jemand erklären, was ich falsch mache?
Antworten:
Die Handbuchseite (oder das Online-GNU-Handbuch ) erklärt so ziemlich alles.
find -exec Befehl {} \;
Für jedes Ergebnis
command {}
wird ausgeführt. Alle Vorkommen von{}
werden durch den Dateinamen ersetzt.;
wird mit einem Schrägstrich versehen, um zu verhindern, dass die Shell ihn interpretiert.find -exec Befehl {} +
Jedes Ergebnis wird angehängt
command
und anschließend ausgeführt. Unter Berücksichtigung der Befehlslängenbeschränkungen kann dieser Befehl möglicherweise mehrmals ausgeführt werden, wobei die Handbuchseite mich unterstützt:Beachten Sie dieses Zitat aus der Handbuchseite:
Aus diesem Grund sind keine Zeichen zwischen
{}
und+
außer Leerzeichen zulässig .+
lässt find erkennen, dass die Argumente genau wie an den Befehl angehängt werden sollenxargs
.Die Lösung
Glücklicherweise kann die GNU-Implementierung von
mv
das Zielverzeichnis als Argument mit einem-t
oder dem längeren Parameter akzeptieren--target
. Die Verwendung wird sein:Ihr
find
Befehl wird:Von der Handbuchseite:
quelle
./test/
zwischen{}
und gesetzt+
, aber zwischen diesen sind keine Nicht-Leerzeichen zulässig.+
Befehl ist ein bisschen seltsam AFAIU, da er die Dateien am "Ende" (und nicht anstelle von{}
) festhält. Warum also{}
überhaupt verwenden - das ist verwirrend. Vielen Dank für die-t
Option, die ich nicht kannte. Es scheint, dass diese Option als-exec +
Problemumgehung für dieses Problem erstellt wurde!Unter Mac OS X ist bei der Verwendung einer ZSH- Shell dasselbe Problem aufgetreten : In diesem Fall gibt es keine
-t
Option fürmv
, sodass ich eine andere Lösung finden musste. Der folgende Befehl war jedoch erfolgreich:Das Geheimnis war , die Zahnspange zu zitieren . Die Klammern müssen sich nicht am Ende des
exec
Befehls befinden.Ich habe unter Ubuntu 14.04 (mit BASH- und ZSH- Shells) getestet , es funktioniert genauso.
Bei Verwendung des
+
Zeichens muss es jedoch tatsächlich am Ende desexec
Befehls stehen.quelle
{}
muss in denfish
undrc
Muscheln zitiert werden , aber nicht inzsh
,bash
noch in irgendwelchen anderen Muscheln der Bourne oder csh Familien.bash
, in der Tat sind die Anführungszeichen nicht notwendig. Seltsamerweise hatte ich ein Problem, wenn ich sie nicht unter MacOS zitierte (mitzsh
). Aber ich habe keinen Mac in Reichweite, um es erneut zu versuchen ...Das Standardäquivalent
find -iname ... -exec mv -t dest {} +
fürfind
Implementierungen, die nicht unterstützt werden,-iname
odermv
Implementierungen, die nicht unterstützt werden,-t
ist die Verwendung einer Shell, um die Argumente neu zu ordnen:Durch die Verwendung
-name '*.[cC][pP][pP]'
vermeiden wir auch die Abhängigkeit vom aktuellen Gebietsschema, um zu entscheiden, welche Großbuchstabenversion vonc
oder verwendet wirdp
.Beachten Sie, dass
+
im Gegensatz dazu;
in keiner Shell etwas Besonderes ist und daher nicht in Anführungszeichen gesetzt werden muss (obwohl das Zitieren nicht schadet, außer natürlich bei solchen Shellsrc
, die\
als Anführungszeichen-Operator nicht unterstützt werden).Der nachlauf
/
in/dest/dir/
ist , so dassmv
mit einem Fehler fehlschlägt statt Umbenennungfoo.cpp
auf/dest/dir
dem Fall, dass nur einecpp
Datei gefunden wurde und/dest/dir
nicht existierte oder war kein Verzeichnis (oder Symlink - Verzeichnis).quelle
quelle
Nein, der Unterschied zwischen
+
und\;
sollte umgekehrt werden.+
Hängt die Dateien an das Ende des Befehls exec an,\;
führt dann den Befehl exec aus und führt den Befehl für jede Datei aus.Das Problem ist,
find . -type f -iname '*.cpp' -exec mv {} ./test/ \+
dass esfind . -type f -iname '*.cpp' -exec mv {} ./test/ +
nicht nötig sein sollte, dem zu entkommen oder das zu beenden+
xargs habe ich schon lange nicht mehr benutzt, aber ich denke, es funktioniert wie +.
quelle
-name "*.cpp"
Ich benutze -iname kaum, es sei denn, ich möchte eine schwierige Regex-Suche durchführen, wie -iname '??? work. * \. Cpp'-iname
und falsch-name
.-iname
ist die Version, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird,-name
und weist keine Unterschiede im Umgang mit regulären Ausdrücken auf. Ich schlage vor, Befehle vor dem Posten auszuprobieren. Ihr Befehl schlägt auch in meiner Shell fehl.