Ich versuche, den folgenden Befehl auszuführen:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" +
Dies gibt einen Fehler zurück:
find: missing argument to -exec
Ich kann nicht sehen, was mit diesem Befehl falsch ist, da er mit der Manpage übereinzustimmen scheint :
-exec Befehl {} +
Diese Variante der Option -exec führt den angegebenen Befehl für die ausgewählten Dateien aus, jedoch Die Befehlszeile wird durch Anhängen jedes ausgewählten Dateinamens am Ende erstellt. Die Gesamtzahl der Aufrufe des Befehls ist viel geringer als die Anzahl der übereinstimmenden Dateien. Die Befehlszeile wird ähnlich wie xargs erstellt Befehlszeilen. Innerhalb des Befehls ist nur eine Instanz von „{}“ zulässig. Der Befehl wird im Startverzeichnis ausgeführt.
Ich habe auch versucht:
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} + find a/folder b/folder -name *.c -o -name *.h -exec "grep -I foobar" {} + find a/folder b/folder -name *.c -o -name *.h -exec "grep -I foobar" "{}" + find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar "{}" + find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar "{}" + find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar "{}" \+
Kommentare
- Haben Sie versucht, der
+
am Ende?find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
- Möglicherweise verwenden Sie eine alte Version von GNU
find
. Obwohl die Variante-exec cmd {} +
POSIX ist und seit den 80er Jahren verfügbar ist, wurde sie von GNU find erst (relativ) kürzlich (2005) hinzugefügt. Was sagt Ihnenfind --version
? - @Koveras, das wäre es dann.
-exec {} +
wurde 2005 in 4.2.12 hinzugefügt. In älteren GNU-Funden können Sie das (Nicht-POSIX)-print0 | xargs -r0
verwenden, um etwas zu erhalten ähnlich.4.1
stammt aus dem Jahr 1994. - JRFerguson wies (in einer gelöschten Antwort) darauf hin, dass das Muster
-name
Argumente sollten in Anführungszeichen gesetzt werden:-name "*.c" -o -name "*.h"
. Dies ist wahr, obwohl es nichts mit dem Fehler-exec
zu tun hat. Sie werden feststellen, dass alle anderen Antworten die Platzhalter in Anführungszeichen setzen, obwohl nur Gilles dies erwähnt. … (Fortsetzung) - (Fortsetzung)… Die Antwort von jlliagre reduziert den Namensausdruck ohne Erklärung auf
-name "*.[ch]"
. Dies hat den Vorteil, dass die Befehlszeile vereinfacht und insbesondere die-o
entfernt wird. Es ist schwierig, Ausdrücke zu finden, die-o
betreffen. Dein ist falsch; Wenn Ihr Befehl so festgelegt ist, dass er nicht ausfällt (wie in Gilles Antwort), wirdgrep
nur auf der.h
ausgeführt Dateien. Sie müssen'(' -name '*.c' -o -name '*.h' ')'
ausführen.
Antwort
Es gab Verschiedene Probleme bei Ihren Versuchen, einschließlich Backticks, die anstelle von Anführungszeichen verwendet wurden (in späteren Änderungen an der Frage entfernt), fehlende Anführungszeichen, wo sie benötigt werden, zusätzliche Anführungszeichen, wo sie unbrauchbar sind, fehlende Klammern zur Gruppe -o
-Klauseln und verschiedene Implementierungen von find
werden verwendet (Einzelheiten finden Sie in den Kommentaren und im Chat).
Der Befehl kann auf jeden Fall folgendermaßen vereinfacht werden:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +
oder sollte eine archaische GNU-Suchversion verwendet werden, sollte dies immer funktionieren:
find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
Kommentare
- Hoppla, sie sollten Anführungszeichen und keine Backticks sein.
- Anführungszeichen wären als
{}
hat keine spezifische Bedeutung für die Shell. - Aus Suchmanpages: “ Die Zeichenfolge ‚ { } ‚ ist Ersetzt durch den aktuellen Dateinamen, der überall dort verarbeitet wird, wo er in den Argumenten des Befehls vorkommt, nicht nur in Argumenten, in denen er allein ist, wie in einigen Versionen von find. Diese beiden Konstruktionen müssen möglicherweise maskiert werden (mit einem ‚ \ ‚) oder in Anführungszeichen gesetzt werden, um sie vor der Erweiterung durch die Shell zu schützen div id = „340c16de68“>
Antwort
“fehlendes Argument für -exec
„bedeutet normalerweise, dass dem Argument für – exec
der Terminator fehlt. Der Terminator muss entweder ein Argument sein, das nur das Zeichen ;
enthält (das in einem Shell-Befehl in Anführungszeichen gesetzt werden muss, daher wird es normalerweise \;
oder ";"
) oder zwei aufeinanderfolgende Argumente, die {}
und +
enthalten.
Stephane Chazelas hat festgestellt , dass Sie eine ältere Version von GNU find verwenden, die -exec … {} +
, nur -exec {} \;
.Obwohl GNU ein später Anwender von -exec … {} +
war, empfehle ich Ihnen, eine weniger antike Tool-Suite zu erwerben (z. B. Cygwin a) >, das git und vieles mehr enthält, oder GNUwin32 , dem git fehlt, das aber nicht über den schlechten Mitarbeiter verfügt, der versucht, Linux zu verwenden Diese Funktion wurde vor über 9 Jahren in Version 4.2.12 hinzugefügt (es war die letzte identifizierte Funktion, die GNU find
gemacht hat) POSIX-kompatibel).
Wenn Sie sich an einen älteren GNU-Fund halten möchten, können Sie -print0
mit xargs -0
um eine ähnliche Funktionalität zu erhalten: Gruppierte Befehlsausführung, die beliebige Dateinamen unterstützt.
find a/folder b/folder -name "*.c" -o -name "*.h" -print0 | xargs -0 grep -I foobar /dev/null
Zitieren Sie immer die Platzhalter auf der find
Befehlszeile. Wenn Sie diesen Befehl andernfalls in einem Verzeichnis ausführen, das .c
-Dateien enthält, wird die nicht zitierte *.c
angezeigt d auf die Liste der .c
-Dateien im aktuellen Verzeichnis erweitert werden.
Hinzufügen von /dev/null
zur grep
Die Befehlszeile ist ein Trick, um sicherzustellen, dass grep immer den Dateinamen druckt, auch wenn find
zufällig eine einzelne Übereinstimmung findet. Bei der GNU-Suche besteht eine andere Methode darin, die Option -H
zu übergeben.
Kommentare
- Was machen Sie? meine mit schlechtem Mitarbeiter, der versucht, Linux zu verwenden, aber wir erzwingen Windows-Stimmung, die Cygwin gibt?
- GNUwin32 hat ‚ nicht erwartet 🙁
- Siehe meine Kommentare zu der Frage.
- Die Anführungszeichen um das Semi arbeiteten in einem package.json-Skript.
Antwort
Wenn ein Befehl wie
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +
den Fehler p zurückgibt >
find: missing argument to -exec
Die wahrscheinliche Ursache ist zu alt. GNU find
unterstützt keine Syntax. -exec mycommand {} +
. In diesem Fall muss durch Ersetzen mit geringer Leistung -exec mycommand {} \;
ausgeführt werden, wodurch die mycommand
einmal für jedes gefundene Ziel ausgeführt wird, anstatt mehrere Ziele zu sammeln und Ausführen des mycommand
nur einmal.
GNU find
doe s unterstützt zB
find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +
nicht, da GNU find
nur die Literalkombination {} +
statt generischer {} additional parameters +
. Beachten Sie, dass zwischen den geschweiften Klammern und dem Zeichen +
nichts stehen darf. Wenn Sie dies versuchen, wird der gleiche Fehler angezeigt:
find: missing argument to -exec
Die Problemumgehung besteht darin, die Syntax {} additional parameters \;
zu verwenden funktioniert, führt den Befehl jedoch einmal für jedes gefundene Ziel aus. Wenn Sie mit GNU find
mehr Leistung benötigen, müssen Sie ein Wrapper-Skript schreiben, mit dem zusätzliche Parameter an die angegebenen Argumente angehängt werden können. So etwas wie
#!/bin/bash exec mycommand "$@" additional parameters
sollte gut genug sein. Wenn Sie keine temporäre Datei erstellen möchten, können Sie die Reihenfolge der Parameter wie folgt ändern:
find . -type f -and -name "*.ttf" -exec bash -c "mycommand "$@" extra arguments" {} +
, wodurch mycommand {list of ttf files} extra arguments
. Beachten Sie, dass Sie möglicherweise Sonderzeichen für die Bash nach dem -c
-Flag doppelt maskieren müssen.
Kommentare
- (1) Der Teil des oben Gesagten, der die Frage tatsächlich beantwortet, wurde bereits von anderen Personen gegeben. (2) Was Sie beschreiben, ist kein Fehler oder Mangel in GNU
find
, sondern das von POSIX a angegebene korrekte Verhalten >. - +1 Endlich jemand, der antwortet, warum zusätzliche Parameter ‚ nicht funktionieren! Es scheint ein Mangel in der POSIX-Definition zu sein.
- Wenn Sie ‚ GNU
find
haben, sind Sie ‚ haben wahrscheinlich GNUcp
. In diesem Fall können Siefind ... -exec cp --target-directory ~/.fonts {} +
verwenden, um die{}
am Ende der Ausführungszeichenfolge beizubehalten.
Antwort
find . -type f -perm 0777 -exec chmod 644 {}\;
hat den Fehler find: missing argument to ``-exec"
.
Durch Hinzufügen von Leerzeichen zwischen {}
und \
wurde Folgendes behoben:
find . -type f -perm 0777 -print -exec chmod 644 {} \;
Kommentare
- In
find
Befehl in der vorliegenden Frage. - In Frage ist es nicht in Ordnung, dass ich verstanden habe, aber das Problem ist das gleiche. “ find: fehlendes Argument zu „ -exec ‚ „, Problem kann aus verschiedenen Gründen auftreten, antwortete ich, weil ich dieselbe Problemstellung sah.
- @Kusalananda Meine Güte, der Noob lieferte eine Lösung für den gemeldeten Fehler, der vom OP sowohl im Titel als auch im Hauptteil der Frage angegeben wird.
- @bvj Die Frage befasst sich ausdrücklich mit der Form
+
der Option-exec
fürfind
. Diese Antwort behebt ein Problem, das der Benutzer, der die Frage stellt, nicht hat.
Antwort
Ich hatte meine Anteil der Kopfschmerzen mit der Exec-Syntax in der Vergangenheit. An den meisten Tagen bevorzuge ich die schönere Bash-Syntax:
for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done
Es gibt einige Einschränkungen, wenn Sie die Dateien als Gruppe behandeln möchten, da jede seriell ausgewertet wird. Sie können die Ausgabe jedoch problemlos an eine andere Stelle weiterleiten.
Kommentare
- Obwohl dies tendenziell funktioniert, ist es erheblich weniger nützlich als die reine Suchversion, da es Dateien mit Leerzeichen im Namen können nicht korrekt verarbeitet werden.
- Nein, ‚ tun dies nicht. Dies wird unterbrochen, sobald die Dateien Leerzeichen und andere „seltsame“ Zeichen enthalten. Dies ist auch komplexer und langsamer als
find … -exec … \;
, daher gibt es ‚ keinen Grund, dies zu verwenden, selbst wenn Sie wissen, dass Ihre Dateinamen lauten tame. - Dies war hilfreich für meine Situation, in der ich mehrere Logikzeilen basierend auf den Dateinamen ausführen musste (z. B. Entfernen von Zeichen, Erstellen von Verzeichnissen und anschließendes Verschieben der Dateien). Der Versuch, mehrere Dinge in einem
exec
zu finden, war für die 5 Minuten, die ich damit verbringen wollte, zu viel Kopfzerbrechen. Meine Dateinamen waren zahm und dies löste mein Problem 🙂