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 grepUnterstützungsoption -r(für den Rückgriff ):
grep -r <search_string> .
--exclude-dir, um die Leistung zu adressieren und wir haben einen Gewinner!
grepBeachten 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-dirist 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-direxklusiv für GNU ist grep. (-:
Eine suboptimale Antwort: Anstatt die Ausgabe von findin zu grepleiten, 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 grepund bedeutet ackder -iSchalter 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 --colorund die -nSchalter (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
ackist großartig, und eine schnellere Version von ackis 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 -ROption ist keine Standardoption, wird jedoch von den meisten gängigen grepImplementierungen unterstützt.
-rstatt -Rüberspringen Symlinks , wenn GNU grep betroffen ist
grepImplementierungen Rekursionen verursachen, denke ich. Ansonsten kommt es darauf an, was du mit "Baum" meinst.
greptun 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 -roder -R(abhängig vom gewünschten Symlink-Handling) ist eine schnelle Option.
Jedoch -d <action>kann manchmal nützlich sein.
Das Schöne daran -dist 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 skipOption 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"