Ich bin ständig auf der Suche nach der Syntax von
find . -name "FILENAME" -exec rm {} \;
hauptsächlich, weil ich nicht sehe, wie genau das -exec
Teil funktioniert. Was bedeuten die Klammern, der Backslash und das Semikolon? Gibt es andere Anwendungsfälle für diese Syntax?
man
Seite steht: Ein Dienstprogrammname oder ein Argument, das nur die beiden Zeichen "{}" enthält, soll durch den aktuellen Pfadnamen ersetzt werden , der mir ausreicht. Außerdem hat es ein Beispiel mit-exec rm {} \;
, genau wie in deiner Frage. Zu meiner Zeit gab es kaum andere Ressourcen als die "große graue Wand", Bücher mit gedrucktenman
Seiten (Papier war billiger als Lagerung). Ich weiß also, dass dies für jemanden ausreicht, der mit dem Thema noch nicht vertraut ist. Ihre letzte Frage ist hier allerdings fair zu stellen. Leider haben weder @Kusalananda noch ich eine Antwort darauf.xargs
es manchmal praktisch ist,find
können mehrere Pfadargumente an den Befehl übergeben werden, ohne dass dieser angegeben wird.-exec command... {} +
(mit+
statt\;
) übergibt so viele Pfade,command...
wie es passt (jedes Betriebssystem hat seine eigene Begrenzung für die Länge einer Befehlszeile). Und wiexargs
die+
terminierte Form vonfind
‚s-exec
Aktion wird auch läuftcommand...
mehrere Male in dem seltenen Fall , dass es zu viele Pfade innerhalb der Grenze zu passen.Antworten:
Diese Antwort besteht aus folgenden Teilen:
-exec
-exec
in Kombination mitsh -c
-exec ... {} +
-execdir
Grundsätzliche Verwendung von
-exec
Die
-exec
Option verwendet ein externes Dienstprogramm mit optionalen Argumenten als Argument und führt es aus.Wenn der String
{}
irgendwo im angegebenen Befehl vorhanden ist, wird jede Instanz durch den Pfadnamen ersetzt, der gerade verarbeitet wird (z./some/path/FILENAME
. B. ). In den meisten Shells müssen die beiden Zeichen{}
nicht in Anführungszeichen gesetzt werden.Der Befehl muss mit einem beendet werden,
;
umfind
zu wissen, wo er endet (da es danach möglicherweise weitere Optionen gibt). Um die Datei;
vor der Shell zu schützen , muss sie in Anführungszeichen als\;
oder gesetzt';'
werden. Andernfalls wird sie von der Shell als Ende desfind
Befehls betrachtet.Beispiel (die
\
am Ende der ersten beiden Zeilen stehen nur für Zeilenfortsetzungen):Dies findet alle regulären Dateien (
-type f
), deren Namen mit dem Muster*.txt
im oder unter dem aktuellen Verzeichnis übereinstimmen . Es wird dann geprüft, ob der Stringhello
in einer der gefundenen Dateien vorkommtgrep -q
(was keine Ausgabe erzeugt, nur einen Exit-Status). Für diejenigen Dateien, die den String enthalten,cat
wird ausgeführt, um den Inhalt der Datei an das Terminal auszugeben.Jeder
-exec
verhält sich auch wie ein "Test" für die von gefundenen Pfadnamenfind
, genau wie-type
und-name
. Wenn der Befehl einen Beendigungsstatus von Null zurückgibt (was "Erfolg" bedeutet), wird der nächste Teil desfind
Befehls berücksichtigt, andernfalls wird derfind
Befehl mit dem nächsten Pfadnamen fortgesetzt. Dies wird im obigen Beispiel verwendet, um Dateien zu finden, die die Zeichenfolge enthaltenhello
, aber um alle anderen Dateien zu ignorieren.Das obige Beispiel zeigt die beiden häufigsten Anwendungsfälle von
-exec
:find
Befehls).Verwendung
-exec
in Kombination mitsh -c
Der Befehl, der ausgeführt werden
-exec
kann, ist auf ein externes Dienstprogramm mit optionalen Argumenten beschränkt. Es-exec
ist nicht möglich, Shell-Built-Ins, Funktionen, Bedingungen, Pipelines, Umleitungen usw. direkt mit zu verwenden, es sei denn, sie sind in eine Artsh -c
Child-Shell eingebunden.Wenn
bash
Funktionen erforderlich sind, verwenden Siebash -c
anstelle vonsh -c
.sh -c
Wird/bin/sh
mit einem Skript ausgeführt, das in der Befehlszeile angegeben wird, gefolgt von optionalen Befehlszeilenargumenten für dieses Skript.Ein einfaches Beispiel für die Verwendung
sh -c
ohnefind
:Dies übergibt zwei Argumente an das untergeordnete Shell-Skript:
Die Zeichenfolge
sh
. Dies ist wie$0
im Skript verfügbar , und wenn die interne Shell eine Fehlermeldung ausgibt, wird dieser Zeichenfolge ein Präfix vorangestellt.Das Argument
apples
ist als verfügbar$1
im Drehbuch, und hatte es mehr Argumente gewesen, dann hätten diese als verfügbar gewesen$2
,$3
usw. Sie würden auch in der Liste vorhanden sein"$@"
(außer$0
denen nicht Teil sein würde"$@"
).Dies ist in Kombination mit nützlich,
-exec
da damit beliebig komplexe Skripte erstellt werden können, die auf die von gefundenen Pfadnamen angewendet werdenfind
.Beispiel: Suchen Sie alle regulären Dateien mit einem bestimmten Dateinamensuffix und ändern Sie dieses Dateinamensuffix in ein anderes Suffix, wobei die Suffixe in Variablen gespeichert werden:
Innerhalb des internen Skripts
$1
wäre das die Zeichenfolgetext
,$2
wäre die Zeichenfolgetxt
und$3
wäre der Pfadnamefind
, der für uns gefunden wurde. Die Parametererweiterung${3%.$1}
würde den Pfadnamen übernehmen und das Suffix.text
daraus entfernen .Oder mit
dirname
/basename
:oder mit hinzugefügten Variablen im internen Skript:
Beachten Sie, dass sich in dieser letzten Variante die Variablen
from
undto
in der untergeordneten Shell von den gleichnamigen Variablen im externen Skript unterscheiden.Das Obige ist die richtige Art, ein beliebiges komplexes Skript von
-exec
mit aufzurufenfind
. Verwenden Siefind
in einer Schleife wieist fehleranfällig und unelegant (persönliche Meinung). Es teilt Dateinamen auf Leerzeichen auf, ruft das Globbing von Dateinamen auf und zwingt die Shell, das gesamte Ergebnis zu erweitern,
find
bevor sie überhaupt die erste Iteration der Schleife ausführt.Siehe auch:
Verwenden
-exec ... {} +
Das
;
am Ende darf durch ersetzt werden+
. Dies führtfind
dazu, dass der angegebene Befehl mit möglichst vielen Argumenten (gefundenen Pfadnamen) ausgeführt wird und nicht einmal für jeden gefundenen Pfadnamen. Die Zeichenfolge{}
muss unmittelbar vor dem auftreten,+
damit dies funktioniert .Hier
find
werden die resultierenden Pfadnamen gesammelt undcat
auf so viele von ihnen wie möglich gleichzeitig ausgeführt.Ebenso wird hier
mv
so wenig wie möglich ausgeführt. Dieses letzte Beispiel erfordert GNUmv
von coreutils (was die-t
Option unterstützt ).Das Verwenden von
-exec sh -c ... {} +
ist auch eine effiziente Möglichkeit, eine Reihe von Pfadnamen mit einem beliebig komplexen Skript zu durchlaufen.Die Grundlagen sind die gleichen wie bei der Verwendung
-exec sh -c ... {} ';'
, aber das Skript benötigt jetzt eine viel längere Liste von Argumenten. Diese können durch Überlaufen"$@"
innerhalb des Skripts durchlaufen werden.Unser Beispiel aus dem letzten Abschnitt, in dem Dateinamensuffixe geändert werden:
Verwenden
-execdir
Es gibt auch
-execdir
(von den meistenfind
Varianten implementiert , aber keine Standardoption).Dies funktioniert
-exec
mit dem Unterschied, dass der angegebene Shell-Befehl mit dem Verzeichnis des gefundenen Pfadnamens als aktuellem Arbeitsverzeichnis ausgeführt wird und{}
den Basisnamen des gefundenen Pfadnamens ohne Pfad enthält (GNUfind
geht dem Basisnamen jedoch weiterhin voran./
, während BSD aktiv istfind
werde das nicht tun).Beispiel:
Dadurch wird jede gefundene
*.txt
-Datei in ein bereits vorhandenesdone-texts
Unterverzeichnis im selben Verzeichnis verschoben, in dem die Datei gefunden wurde . Die Datei wird auch umbenannt, indem das Suffix hinzugefügt.done
wird.Dies wäre etwas kniffliger,
-exec
da wir den Basisnamen der gefundenen Datei herausfinden müssten, um{}
den neuen Namen der Datei zu bilden. Wir benötigen auch den Verzeichnisnamen von{}
, um dasdone-texts
Verzeichnis richtig zu lokalisieren .Mit
-execdir
werden einige Dinge wie diese einfacher.Die entsprechende Operation using
-exec
anstelle von-execdir
müsste eine untergeordnete Shell verwenden:oder,
quelle
-exec
Nimmt ein Programm und Argumente und führt es aus. Einige Shell-Befehle bestehen nur aus einem Programm und Argumenten, viele jedoch nicht. Ein Shell-Befehl kann Umleitung und Piping enthalten.-exec
kann nicht (obwohl das ganzefind
umgeleitet werden kann). Ein Shell-Befehl kann; && if
etc verwenden.-exec
kann nicht, obwohl-a -o
einige tun können. Ein Shell-Befehl kann ein Alias, eine Shell-Funktion oder eine integrierte Funktion sein.-exec
kann nicht. Ein Shell-Befehl kann vars erweitern.-exec
kann nicht (obwohl die äußere Schale, die diefind
Dose läuft ). Ein Shell-Befehl kann$(command)
jedes Mal anders eingesetzt werden.-exec
kann nicht. ...-exec
nicht - obwohlfind
er Dateien genauso durchlaufen kann wie die meisten Globs, ist das also selten erwünscht.sh
selbst sein, der in der Lage ist, all diese Dinge zu tunfind -exec cmd arg \;
ruft nicht eine Shell eine Shell - Befehlszeile zu interpretieren, es läuftexeclp("cmd", "arg")
direkt, nichtexeclp("sh", "-c", "cmd arg")
(für die würde die Schale tun das Äquivalent am Ende ,execlp("cmd", "arg")
wenncmd
nicht builtin).find
Argumente nach-exec
und bis;
oder+
zusammen mit den Argumenten des Befehls ausgeführt werden sollen, wobei jede Instanz eines{}
Arguments durch die aktuelle Datei (mit;
) und{}
als letztes Argument zuvor+
durch eine Liste von Dateien ersetzt wird als separate Argumente (in dem{} +
Fall). IOW-exec
nimmt mehrere Argumente, die von einem beendet;
oder{}
+
.