Wie führe ich find -exec aus?

477

Ich möchte die Dateien im aktuellen Verzeichnis finden, die den Text "chrome" enthalten.

$ find . -exec grep chrome
find: missing argument to `-exec'

Was mache ich falsch?

ripper234
quelle
Siehe auch
Wildcard
Ich habefind: Only one instance of {} is supported with -exec ... +
Costa
2
Siehe auch: Verwendung -execmitfind
Kusalananda

Antworten:

710

Sie haben ein ;(hier geflüchtet, um \;zu verhindern, dass die Shell es interpretiert) oder ein +und ein verpasst {}:

find . -exec grep chrome {} \;

oder

find . -exec grep chrome {} +

findwird ausgeführt grepund {}durch die gefundenen Dateinamen ersetzt. Der Unterschied zwischen ;und +besteht darin, dass für jede Datei ;ein einziger grepBefehl ausgeführt wird, wohingegen bei +möglichst vielen Dateien als Parameter grepauf einmal angegeben werden.

bmk
quelle
30
Wenn Sie das \; Das Ende des Konstrukts grep wird dateiweise übergeben, sodass standardmäßig nicht der Dateiname, sondern nur die übereinstimmenden Zeilen angezeigt werden. Verwenden Sie stattdessen grep -lsdas Konstrukt find, um eine Dateiliste zu erhalten .
Caleb
9
find . -exec grep foo {} +zeigt dir eine Ausgabe wie diese./dir/file.py:from foo import bar
sg
10
find . -exec grep foo {} \;zeigt dir die Ausgabe wie folgtfrom foo import bar
sg
9
find . -exec grep -l foo {} +zeigt dir die Ausgabe wie ./dir/file.py
sg
8
find . -exec grep -l foo {} \;zeigt dir die Ausgabe wie folgt./dir/file.py
sg
46

Sie müssen dafür überhaupt nicht verwenden find. grep ist in der Lage, das Öffnen der Dateien entweder aus einer globalen Liste von allem im aktuellen Verzeichnis heraus zu handhaben:

grep chrome *

... oder auch rekursiv für Ordner und alles darunter:

grep chrome . -R
Caleb
quelle
22
grep wird ersticken, wenn die Erweiterung ARG_MAX überschreitet. -R ruft alles auf, während find verwendet wird. Man kann einfacher Primitive hinzufügen, um bestimmte Dateien (-name usw.) auszuschließen oder nicht einmal Teilbäume (-prune) aufzurufen.
Mel
6
Gute Punkte @Mel. Mein Punkt war, dass die fragende Partei höchstwahrscheinlich die Dinge komplexer machte, als sie es sein musste, indem sie vorstellte, findwann grepsie die Arbeit erledigen konnte. In einigen Fällen wäre es jedoch effektiver, find zu verwenden, um die Dateiliste vor dem Verlassen zu verfeinern zu greifen.
Caleb
4
@Mel verschluckt grepsich in einem solchen Fall nicht, exectut es.
Chris Down
Funktioniert nur, wenn sich alle Dateien im selben Verzeichnis befinden, nicht wenn sie über Unterverzeichnisse verteilt sind.
Yaba
1
@Yaba Meine Antwort gibt an, wie mit Dateien umgegangen wird, die über Unterverzeichnisse verteilt sind.
Caleb
18
find . | xargs grep 'chrome'

Sie können auch tun:

find . | xargs grep 'chrome' -ls

Das erste zeigt Ihnen die Zeilen in den Dateien, das zweite listet nur die Dateien auf.

Calebs Wahl ist ordentlicher, weniger Tastenanschläge.

Mathew
quelle
11
Das Problem dabei xargsist, dass erwartet wird, dass seine Eingabe auf eine eigenartige Weise zitiert wird, finddie nicht produziert. Funktioniert find … | xargs …also nicht, wenn Sie Dateinamen mit Leerzeichen oder haben \'".
Gilles
3
@ Gilles Sie können dieses Problem umgehen, indem Sie find . | xargs -n1 -iX grep "X" 'chrome'so etwas wie verwenden , dass Argumente einzeln eingegeben und in Anführungszeichen gesetzt werden. Offensichtlich ist dies eine schrecklich ineffiziente Art, mit diesem Beispiel umzugehen, aber für einige Situationen ist es schön.
Caleb
Der Vollständigkeit halber sollten wir auch die Option -i für die Unterscheidung zwischen Groß- und Kleinschreibung mit 'grep' erwähnen. Es gibt auch -iname für Groß- und Kleinschreibung.
Mathew
9
@Caleb: Die einzige 100% zuverlässige Möglichkeit, xargsmit Linux-Dateinamen umzugehen find ... -print0 | xargs -0, ist die Verwendung von NUL als Trennzeichen. Alternative - xargs -d '\n'Verwenden von Zeilenvorschub als Trennzeichen, 99% Zuverlässigkeit.
Grawity
Ich benutze dies oft, aber es wird für sehr lange Listen von Dateinamen fehlschlagen, an welchem ​​Punkt find -exec der Gewinner wird.
Spacemoose
5

Suchen ist eine Möglichkeit und Sie können the_silver_searcheralles versuchen, was Sie tun müssen, ist

ag chrome

Es durchsucht alle Dateien (einschließlich Unterverzeichnisse) nach Chrome und ist schneller als es zu finden ist

Fragen und lernen
quelle
Es gibt auch pt (Platinum Searcher, verfügbar unter github.com/monochromegane/the_platinum_searcher ), das, meiner Meinung nach, die Arbeit schneller erledigt - möglicherweise spielt es keine Rolle, wenn es nur wenige Dateien gibt.
Hopping Bunny
1

So zeigen Sie eine Liste von Dateien anstelle von Zeilen an:

grep -l "chrome" *

oder:

grep -r -l "chrome" .
mateusz.szymborski
quelle
1

Hier ist ein Beispiel, wie ich normalerweise find / exec verwende ...

find  . -name "*.py" -print -exec fgrep hello {} \;

Dadurch wird rekursiv nach allen .py-Dateien gesucht, und für jede Datei werden der Dateiname und die fgrep-Zeichen für "Hallo" für diese (für jede) Datei ausgegeben. Die Ausgabe sieht wie folgt aus (hat gerade eine ausgeführt):

./r1.py
./cgi-bin/tst1.py
print "hello"
./app/__init__.py
./app/views.py
./app/flask1.py
./run.py
./tst2.py
print "hello again"
jon
quelle
1
Sie sollten sich nicht in Ihren Workflow einmischen, aber vielleicht möchten Sie: find . -name "*.py" -exec fgrep -l hello {} \; - Die Dateinamen der übereinstimmenden Dateien werden gedruckt, und sonst nichts.
Jeff Schaller