find: fehlendes Argument zu -exec

18

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 nicht stimmt, da er mit der Manpage übereinstimmt:

-exec Befehl {} +

Diese Variante der Option -exec führt den angegebenen Befehl für die ausgewählten Dateien aus. Die Befehlszeile wird jedoch erstellt, indem jeder ausgewählte Dateiname am Ende angehängt wird. Die Gesamtzahl der Aufrufe des Befehls ist viel geringer als die Anzahl der übereinstimmenden Dateien. Die Befehlszeile ist in etwa so aufgebaut wie die Befehlszeilen von xargs. 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 '{}' \+
David Kennedy
quelle
Haben Sie versucht, +am Ende der Flucht ? find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+
Jayhendren
3
Möglicherweise verwenden Sie eine alte Version von GNU find. Obwohl die -exec cmd {} +Variante POSIX ist und seit den 80er Jahren verfügbar ist, hat GNU find sie erst (relativ) vor kurzem (2005) hinzugefügt. Was find --versionsagt dir das?
Stéphane Chazelas
2
@Koveras, das wäre es dann. -exec {} +wurde in 4.2.12 im Jahr 2005 hinzugefügt. In älteren GNU-Funden können Sie das (nicht-POSIX) verwenden -print0 | xargs -r0, um etwas Ähnliches zu erhalten. 4.1ist von 1994.
Stéphane Chazelas
1
JRFerguson wies darauf hin (in einer Antwort , die gelöscht wurde) , dass die -nameMuster Argumente sollen zitiert werden: -name "*.c" -o -name "*.h". Dies ist wahr, obwohl es nichts mit dem -execFehler zu tun hat. Sie werden feststellen, dass alle anderen Antworten die Platzhalter in Anführungszeichen setzen, obwohl nur Gilles dies erwähnt. … (Fortsetzung)
G-Man sagt, dass Monica
1
(Fortsetzung) ... Die Antwort von jlliagre reduziert den Namensausdruck auf -name "*.[ch]"ohne Erklärung. Dies hat den Vorteil, dass die Befehlszeile vereinfacht und insbesondere die Befehlszeile entfernt wird  -o. Es -oist schwierig, Ausdrücke zu finden, die etwas betreffen . Dein ist falsch; Wenn Ihr Befehl so festgelegt ist, dass er nicht ausfällt (wie in Gilles 'Antwort), wird er grepnur für die .hDateien ausgeführt. Das musst du tun '(' -name '*.c' -o -name '*.h' ')'.
G-Man sagt, dass Monica

Antworten:

18

Sie müssen die einfachen Anführungszeichen entfernen, die Sie verwenden {}. Der Befehl kann wie folgt vereinfacht werden:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

Wenn Sie eine archaische GNU-Find-Version verwenden, sollte dies weiterhin funktionieren:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;
jlliagre
quelle
Ups, sie sollten Zitate sein, keine Backticks.
David Kennedy
Anführungszeichen wären nutzlos, da sie {}für die Shell keine spezifische Bedeutung haben.
Juli
In den Manpages zum Suchen: "Die Zeichenfolge '{}' wird durch den aktuellen Dateinamen ersetzt, der an allen Stellen verarbeitet wird, an denen sie in den Argumenten des Befehls vorkommt, nicht nur in Argumenten, an denen sie alleine ist, wie in einigen Versionen von Suchen. Beide Konstruktionen müssen möglicherweise mit einem Escapezeichen ("\") versehen oder in Anführungszeichen gesetzt werden, um sie vor der Erweiterung durch die Shell zu schützen. "
David Kennedy
1
Ich habe das zwar in der Bedienungsanleitung gelesen, aber die Tatsache, dass es keine Shell gibt, die ich kenne, erfordert das Zitieren der geschweiften Klammern. Welche Shell benutzt du?
Juli
bash. Mit oder ohne Anführungszeichen bekomme ich den Fehler trotzdem.
David Kennedy
10

"Fehlendes Argument zu -exec" bedeutet normalerweise, dass dem Argument zu - execdas Abschlusszeichen fehlt. Das Abschlusszeichen muss entweder ein Argument sein, das nur das Zeichen enthält ;(das in einem Shell-Befehl in Anführungszeichen gesetzt werden muss, damit es normalerweise geschrieben wird \;oder ';'), oder zwei aufeinanderfolgende Argumente, die {}und enthalten +.

Stephane Chazelas identifiziert , dass Sie eine ältere Version von GNU find verwenden , die nicht unterstützt -exec … {} +, nur -exec {} \;. Obwohl GNU ein später Anwender von war -exec … {} +, empfehle ich Ihnen eine weniger antike Tool-Suite (wie Cygwin , die Git und vieles mehr enthält, oder GNUwin32 , der Git fehlt, bei dem es aber keine schlechten Angestellten gibt) -zu-verwenden-Linux-aber-wir-auferlegen-Windows-Vibe, die Cygwin gibt). Diese Funktion wurde vor über 9 Jahren in Version 4.2.12 hinzugefügt (es war die letzte identifizierte Funktion, die GNU findPOSIX-kompatibel gemacht hat).

Wenn Sie sich an einen älteren GNU-Fund halten möchten, können Sie -print0mit xargs -0eine ähnliche Funktionalität 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 in der findBefehlszeile. Andernfalls wird der Befehl ohne .cAnführungszeichen *.cin die Liste der .cDateien im aktuellen Verzeichnis aufgenommen , wenn Sie ihn in einem Verzeichnis ausführen, das Dateien enthält .

Das Hinzufügen /dev/nullzur grepBefehlszeile ist ein Trick, um sicherzustellen, dass grep immer den Dateinamen ausgibt, auch wenn findzufällig eine einzelne Übereinstimmung gefunden wird. Bei GNU find besteht eine andere Methode darin, die Option zu übergeben -H.

Gilles 'SO - hör auf böse zu sein'
quelle
1
Was meinen Sie mit dem schlechten Angestellten, der versucht, Linux zu benutzen, aber Windows-Vibe auferlegt, das Cygwin gibt?
David Kennedy
GNUwin32 hat nicht erwartet :(
David Kennedy
Siehe meine Kommentare zu der Frage.
G-Man sagt, dass Monica
Die Anführungszeichen rund um das Semi funktionierten innerhalb eines package.json-Skripts.
bvj
2

Wenn ein Befehl wie

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +

Gibt einen Fehler zurück

find: missing argument to -exec

die wahrscheinliche Ursache ist zu altes GNU, finddas keine Syntax unterstützt -exec mycommand {} +. In diesem Fall muss ein leistungsarmer Ersatz ausgeführt -exec mycommand {} \;werden, der mycommandeinmal für jedes gefundene Ziel ausgeführt wird, anstatt mehrere Ziele zu sammeln und mycommandnur einmal auszuführen .

GNU unterstützt findjedoch nicht z

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

weil GNU findnur wörtliche Kombinationen {} +statt allgemeinerer unterstützt {} additional parameters +. Beachten Sie, dass sich zwischen den geschweiften Klammern und dem +Zeichen nichts befinden darf . Wenn Sie dies versuchen, erhalten Sie den gleichen Fehler:

find: missing argument to -exec

Die Problemumgehung besteht darin, eine Syntax zu verwenden, {} additional parameters \;die funktioniert, den Befehl jedoch für jedes gefundene Ziel einmal ausführt. Wenn Sie mehr Leistung mit GNU benötigen, müssen findSie ein Wrapper-Skript schreiben, das zusätzliche Parameter an die angegebenen Argumente anhängen kann. 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 mithilfe eines Einzeilers ändern:

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +

was ausgeführt wird mycommand {list of ttf files} extra arguments. Beachten Sie, dass Sie möglicherweise Sonderzeichen für die Bash nach dem -cFlag doppelt maskieren müssen .

Mikko Rantalainen
quelle
(1) Der Teil des Obigen, 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 korrekte Verhalten, das von POSIX angegeben wird .
G-Man sagt, dass Monica
1
+1 Endlich jemand, der antwortet, warum zusätzliche Parameter nicht funktionieren! Es scheint ein Mangel in der POSIX-Definition zu sein.
Jonathan
Wenn Sie GNU haben, haben findSie wahrscheinlich GNU cp. In diesem Fall können Sie find ... -exec cp --target-directory ~/.fonts {} +das {}am Ende der Ausführungszeichenfolge behalten .
Roaima
1

find . -type f -perm 0777 -exec chmod 644 {}\;

habe Fehler find: missing argument to ``-exec'.

Leerzeichen dazwischen einfügen {}und \korrigieren:

find . -type f -perm 0777 -print -exec chmod 644 {} \;

ShreePool
quelle
1
Der findBefehl in der vorliegenden Frage enthält kein solches Problem .
Kusalananda
In Frage ist es nicht in Ordnung, dass ich verstanden habe, aber das Problem ist dasselbe "find: missing argument to` `-exec '", Problem kann aus verschiedenen Gründen auftreten-2, antwortete ich, weil ich die gleiche Problemstellung gesehen habe.
ShreePool
@ Kusalananda Meine Güte, der Noob hat eine Lösung für den gemeldeten Fehler geliefert, der vom OP sowohl im Titel als auch im Hauptteil der Frage angegeben wird.
bvj
@bvj Die Frage befasst sich explizit mit der +Form der -execOption zu find. Diese Antwort behebt ein Problem, das der Benutzer, der die Frage stellt, nicht hat.
Kusalananda
-1

Ich hatte in der Vergangenheit einige Kopfschmerzen mit der Exec-Syntax. 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 Datei seriell ausgewertet wird. Sie können die Ausgabe jedoch auch an eine andere Stelle weiterleiten

tolster710
quelle
1
Dies ist in der Regel weniger nützlich als die Pure-Find-Version, da Dateien mit Leerzeichen im Namen nicht korrekt verarbeitet werden können.
Etan Reisner
5
Nein, tu das nicht. Dies bricht ab, sobald die Dateien Leerzeichen und andere „komische“ Zeichen enthalten. Dies ist auch komplexer und langsamer als find … -exec … \;, sodass es keinen Grund gibt, dies zu verwenden, selbst wenn Sie wissen, dass Ihre Dateinamen zahm sind.
Gilles 'SO- hör auf böse zu sein'
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 zu erledigen, bereitete mir in execden 5 Minuten, die ich damit verbringen wollte, zu viel Kopfschmerzen. Meine Dateinamen waren zahm und das löste mein Problem :)
gMale