Wenn ich einen ganzen Baum nach Inhalten durchsuchen möchte, verwende ich
find . -type f -print0 | xargs -0 grep <search_string>
Gibt es einen besseren Weg, dies in Bezug auf Leistung oder Kürze zu tun?
Wenn ich einen ganzen Baum nach Inhalten durchsuchen möchte, verwende ich
find . -type f -print0 | xargs -0 grep <search_string>
Gibt es einen besseren Weg, dies in Bezug auf Leistung oder Kürze zu tun?
Antworten:
Überprüfen Sie, ob Ihre grep
Unterstützungsoption -r
(für den Rückgriff ):
grep -r <search_string> .
--exclude-dir
, um die Leistung zu adressieren und wir haben einen Gewinner!
grep
Beachten Sie nur, dass dies nicht portabel ist, jedoch von den neuesten FreeBSD- und Linux-Distributionen unterstützt wird. Und warum --exclude-dir
? Haben Sie nicht darum gebeten, einen ganzen Baum zu durchsuchen ?
--exclude-dir
ist in meinem Anwendungsfall praktisch (da Teile des Teilbaums groß, aber nutzlos sind) und ich habe nach der Leistung gefragt ... aber Sie haben Recht, das ist nicht erforderlich.
--exclude-dir
exklusiv für GNU ist grep
. (-:
Eine suboptimale Antwort: Anstatt die Ausgabe von find
in zu grep
leiten, könnten Sie einfach laufen
find . -type f -exec grep 'research' {} '+'
und voila, ein befehl statt zwei!
Erklärung:
find . -type f
Finden Sie alle regulären Dateien in.
-exec grep 'research'
grep "Forschung"
{}
im gefundenen Dateinamen
'+'
Verwenden Sie einen Befehl pro Dateiname und nicht ein Mal pro Dateiname.
Nb: ';'
damit wäre einmal pro Dateiname gewesen.
Wenn Sie das zum Verarbeiten von Quellcode verwenden, können Sie nachsehen ack
, wo Sie auf einfache Weise nach Codebits suchen können.
Bearbeiten:
Sie können diese Forschung ein wenig erweitern. Erstens können Sie den -name ''
Schalter von verwenden find
, um nach Dateien mit einem bestimmten Benennungsmuster zu suchen.
Zum Beispiel :
Nur Dateien, die Protokollen entsprechen: -name '*.log'
Nur Dateien, die c-Headern entsprechen, bei den Dateinamenerweiterungen können Sie jedoch weder Groß- noch Kleinbuchstaben verwenden: -iname *.c
Anmerkung: Wie für grep
und bedeutet ack
der -i
Schalter in diesem Fall , dass die Groß- und Kleinschreibung nicht beachtet wird.
In diesem Fall wird grep ohne Farbe und ohne Zeilennummern angezeigt.
Sie können , dass mit der Änderung --color
und die -n
Schalter (Farbe und Linien Nummern in Dateien respectively).
Am Ende können Sie etwas haben wie:
find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'
zum Beispiel
$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+'
./test2/target.c:1:hello
ack
ist großartig, und eine schnellere Version von ack
is ag
(the silver searcher , geoff.greer.fm/ag )
-name '*.log'
Es ist schneller.
Wenn Sie in Unterverzeichnisse zurückkehren möchten:
grep -R 'pattern' .
Die -R
Option ist keine Standardoption, wird jedoch von den meisten gängigen grep
Implementierungen unterstützt.
-r
statt -R
überspringen Symlinks , wenn GNU grep betroffen ist
grep
Implementierungen Rekursionen verursachen, denke ich. Ansonsten kommt es darauf an, was du mit "Baum" meinst.
grep
tun sollte. Wenn der Benutzer symbolische Linkschleifen in seiner Verzeichnisstruktur hat, ist das das Problem des Benutzers :-)
/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...
mich nie verlaufen in (-XI mag Werkzeuge, die mich babysitten (es sei denn, sie bieten seltsame Magie, die sie "KI" nennen). (-;
Wie oben erwähnt -r
oder -R
(abhängig vom gewünschten Symlink-Handling) ist eine schnelle Option.
Jedoch -d <action>
kann manchmal nützlich sein.
Das Schöne daran -d
ist der Befehl skip, der das "grep: directory_name: Is a directory" zum Schweigen bringt, wenn Sie nur die aktuelle Ebene durchsuchen möchten.
$ grep foo *
grep: q2: Is a directory
grep: rt: Is a directory
$ grep -d skip foo *
$
und natürlich:
$ grep -d recurse foo *
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).
$
Die -d skip
Option ist in einem anderen Skript WIRKLICH praktisch, sodass Sie sie nicht benötigen 2> /dev/null
. :)
Wenn Sie mit vielen Dateien arbeiten, wird das grep schneller ausgeführt, wenn Sie die zu durchsuchenden Dateien zurückschneiden, anstatt alle Dateien in Unterordnern zu durchsuchen.
Ich benutze manchmal dieses Format:
grep "primary" `find . | grep cpp$`
Alle Dateien in Unterordner von .
diesem Ziel cpp
. Dann grep diese Dateien für "primäre".
Wenn Sie möchten, können Sie diese Ergebnisse in weitere grep-Aufrufe umleiten:
grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"