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 Ihnen find --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), wird grep 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“>
  • Ich habe das zwar auf der Handbuchseite gelesen, aber Tatsache ist, dass es keine Shell gibt, die mir ‚ bekannt ist das erfordert das Zitieren der geschweiften Klammern. Welche Shell verwenden Sie?
  • bash. Mit oder ohne Anführungszeichen erhalte ich trotzdem den Fehler.
  • 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 GNU cp. In diesem Fall können Sie find ... -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ür find. 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 🙂

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.