Wie kann ich die Ergebnisse von FIND mit -EXEC erfassen und trotzdem in eine Datei ausgeben?

64

Besser an Beispielen erklären.

Ich kann:

find . -name "*.py" -type f > output.txt

Aber wie kann ich die Ausgabe in der gleichen Datei speichern für:

find . -name "*.py" -type f -exec grep "something" {} \

Ich kann es nicht einfach tun

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
bakytn
quelle

Antworten:

105

Wenn ich Sie richtig verstehe, möchten Sie Folgendes tun:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

FindAlle Dateien mit der Erweiterung py, grepnur Zeilen, in denen somethingdie Zeilen enthalten und gespeichert sind output.txt. Wenn die Datei etwas enthält, wird sie ersetzt.

Bearbeiten: Mit -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

Ich beziehe Chris Downs Kommentar hier ein. Der obige Befehl wird grepso oft ausgeführt, wie findVorkommen gefunden werden. Wenn Sie jedoch das ;durch a ersetzen +, grepwird mit der Ausgabe von findverkettet (bis zu einer bestimmten Grenze) aufgerufen . Weitere Informationen zu diesem Thema finden Sie in der Frage Verwenden von Semikolon (;) vs plus (+) mit exec in find .

Johnny
quelle
16
Verwenden Sie +stattdessen \;, um die Ausführungszeit erheblich zu verkürzen (da Argumente vor der Ausführung verkettet werden, bis ARG_MAX).
Chris Down
Jetzt verstehe ich die Kraft von Xargs! Vielen Dank!
6.
4
Verwenden grep -HSie diese Option, wenn Sie den Dateinamen der Datei in die Ausgabe aufnehmen möchten.
Steinar
18

Wenn Sie alle übereinstimmenden Zeilen in allen Dateien speichern möchten, output.txtfunktioniert Ihr letzter Befehl, außer dass Sie die erforderlichen Zeilen ;am Ende des Befehls fehlen .

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

Wenn Sie möchten, dass bei jedem Durchlauf grepeine Ausgabe in eine andere Datei erfolgt, führen Sie eine Shell aus, um den Namen der Ausgabedatei zu berechnen und die Umleitung durchzuführen.

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
Gilles 'SO - hör auf böse zu sein'
quelle
der letzte wirklich schön: D
bakytn
Um die Antwort von @gilles zu erweitern und sie ein wenig informativer zu gestalten, insbesondere wenn die Liste der Dateien, mit denen Sie zu tun haben, groß ist, können Sie den Dateinamen (relativen Pfad) jeder Datei zusammen mit den auf diese Weise ermittelten Ergebnissen angeben : find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt Und wenn Sie die Zeilennummern der Grep'ed-Zeilen sehen möchten, können Sie natürlichgrep -n "something"
JJMpls
9

Für den Datensatz grepgibt es --includeund --excludeArgumente, mit denen Sie die von ihm durchsuchten Dateien filtern können:

grep -r --include="*.py" "something" > output.txt
hunse
quelle
2
Zumindest GNU grep.
phk
2

Verwendung tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

Der Nachteil ist , wenn Sie alle Dateien mit Sonderzeichen (inklusive Leerzeichen) , dass xargsund grepnicht gut mit ( a file.txtals zwei Dateien interpretiert werden, aund file.txt). Die Alternative dazu ist, entweder das -xoder zu verwenden -print0, aber eines davon verschmutzt Ihr output.txt. Das -xwird verwendet \, um bestimmte Sonderzeichen zu maskieren, und dies wird in output.txt. Das -print0verwendet ein Null-Byte als Feldtrennzeichen (was ebenfalls erforderlich ist xargs -0) und output.txtsieht aus wie eine lange zusammenhängende Textzeile.

Wie Sie damit umgehen (oder nicht), liegt bei Ihnen.

Bahamat
quelle