Verwendung des Befehls "grep" zum Suchen von Text einschließlich Unterverzeichnissen


373

Ich möchte alle Dateien finden, die eine bestimmte Textfolge enthalten. Der grepBefehl funktioniert, aber ich kann ihn nicht für jedes Verzeichnis verwenden (ich kann ihn nur für mein aktuelles Verzeichnis ausführen). Ich habe versucht zu lesen man grep, aber es brachte keine Hilfe.


grep -RIn <Ihr Muster> * Sucht aus den aktuellen Verzeichnissen in allen Textdateien. Ich bin mir nicht sicher, wie ich meine Suche in rekursiven

1
Platzhalter mit der --include="*.C"Option @ user311346 dank @Lekensteyn.
Bob Stein

Verwenden Sie die Kombination find und grep, um rekursiv nach einer Zeichenfolge in aktuellen und allen Unterverzeichnissen zu suchen. Check this wilddiary.com/find-files-containing-my-text
Drona

Antworten:


487

Es wäre besser zu benutzen

grep -rl "string" /path

wo

  • -r(oder --recursive) Option wird verwendet, um auch alle Unterverzeichnisse von zu durchlaufen /path, wohingegen
  • -lDie --files-with-matchesOption (oder ) wird verwendet, um nur die Dateinamen der übereinstimmenden Dateien und nicht die übereinstimmenden Zeilen zu drucken (dies könnte auch die Geschwindigkeit verbessern, da das grepLesen einer Datei bei der ersten Übereinstimmung mit dieser Option beendet wird).

13
Wenn es sich bei "Zeichenfolge" um ein zu suchendes Textmuster handelt, ist es besser, diese Funktion zu verwenden. Andernfalls kann es zu Problemen kommen, wenn die Zeichenfolge Punkte oder Sonderzeichen enthält, die in regulären Ausdrücken eine Bedeutung haben, und nicht nur einen Punkt, der als Zeichenfolge gefunden werden sollte , wie es ist. Dann würde ich -rlFSchalter verwenden, -Ffür "feste Zeichenfolge" (und nicht regexp - zum Beispiel). Natürlich, wenn die Aufgabe Regexps verwendet hat, dann entschuldigen Sie mich. Klar, die gleiche Theorie ohne -r auch, ich sehe oft, dass die Leute Grep-Suchen "Text" annehmen und es Probleme verursachen kann, welche speziellen, die etwas als Regexp bedeuten.
LGB

4
Es gibt auch das -iFlag, das Groß- und Kleinschreibung ignoriert.
Marco Ceppi

3
Ich möchte nur die --recursiveOption zeigen , es gibt Tonnen von Optionen und Nutzungsszenarien, über die man sprechen kann. Ich begann mit der von @dmityugov akzeptierten Antwort und änderte sie, um ohne zu arbeiten find.
Enzotib

1
@NN: done :-)
Enzotib

3
@ ScottBiggs: mit der Option--include '*.h'
Enzotib

167

Wenn Sie nach übereinstimmenden Zeilen in Dateien suchen, lautet mein Lieblingsbefehl:

grep -Hrn 'search term' path/to/files
  • -H bewirkt, dass der Dateiname gedruckt wird (impliziert, wenn mehrere Dateien durchsucht werden)
  • -r führt eine rekursive Suche durch
  • -n bewirkt, dass die Zeilennummer gedruckt wird

path/to/fileskann sein ., im aktuellen Verzeichnis zu suchen

Weitere Optionen, die ich sehr nützlich finde:

  • -IBinärdateien ignorieren (Ergänzung: -aAlle Dateien als Text behandeln)
  • -Fsearch termals wörtlicher Ausdruck behandeln , nicht als regulärer Ausdruck
  • -i Suche ohne Berücksichtigung der Groß- / Kleinschreibung
  • --color=alwaysErzwingen von Farben, auch wenn diese durchgeleitet werden less. Um lessUnterstützungsfarben zu erstellen, müssen Sie die -rOption verwenden:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dirnützlich zum Ausschließen von Verzeichnissen wie .svnund .git.

Beispielausgabe


13
-Hauf einem Ordner ist redundant, wenn es mehr als eine Datei gibt, wie es wahrscheinlich ist. Tatsächlich steht auf der Manpage-H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search.
enzotib

Das wusste ich nicht, es hat immer so funktioniert, wie ich es erwartet hatte. Dies ist mein Standardbefehl beim Suchen nach Dateien.
Lekensteyn

1
Gibt es eine Möglichkeit, nur Dateien mit der Erweiterung .a zu berücksichtigen (und dies mit -r zu kombinieren)?
user2413

6
@ user2413 Try--include '*.*'
Lekensteyn

1
@alper Trygrep --exclude='*~' ...
Lekensteyn

24

Ich glaube, Sie können so etwas verwenden:

find /path -type f -exec grep -l "string" {} \;

Erklärung aus Kommentaren

findist ein Befehl, mit dem Sie Dateien und andere Objekte wie Verzeichnisse und Verknüpfungen in Unterverzeichnissen eines bestimmten Pfads finden können. Wenn Sie keine Maske angeben, der Dateinamen entsprechen sollen, werden alle Verzeichnisobjekte aufgelistet.

  • -type f Gibt an, dass nur Dateien, keine Verzeichnisse usw. verarbeitet werden sollen.
  • -exec grepGibt an, dass für jede gefundene Datei der Befehl grep ausgeführt werden soll, wobei der Dateiname als Argument übergeben wird, indem er {}durch den Dateinamen ersetzt wird

3
Nur für diejenigen, die es nicht wissen, -name '*.py'beschränkt das Hinzufügen die Übereinstimmungen auf Dateien, die mit ".py" enden.
Daniel F

Ich mag, dass dies Clients abdeckt, die -R nicht in ihrem grep-Befehl implementiert haben.
Aviose

Wenn Sie die übereinstimmende Zeile UND den Dateinamen drucken möchten, machen Sie Folgendes:... -exec bash -c 'grep -r "mystring" {} && echo {}' \;
Donn Lee

Was ist die relative Leistung, um nur grep direkt zu verwenden?
Jonathan

19

Mein Standardbefehl ist

grep -Rin string *

Ich benutze ein Kapitol 'R', weil lses rekursiv verwendet wird. Da grep beides akzeptiert, gibt es keinen Grund, es nicht zu benutzen.

EDIT: per HVNSweeting werden anscheinend symlinks -Rfolgen wo wie -rnicht.


1
Um auch in versteckten Dateien zu suchen, führen Sie shopt -s dotglob(merken Sie sich -sals "set"). Seien Sie vorsichtig, wenn Sie Dateien entfernen. Wenn Sie dotglob aktiviert haben, rm -r *wird alles aus dem aktuellen Verzeichnis entfernt, aber auch das darüber liegende Verzeichnis, da es ..übereinstimmt. Verwenden Sie shopt -u dotglob("unset"), um dotglob zu deaktivieren . Die Änderungen sind jedoch nur vorübergehend und gelten nur für die aktuelle Shell.
Lekensteyn

Ich habe das vergessen. Gibt es eine Möglichkeit, es für eine der einen Zeile festzulegen? sowas shopt -s dotglob & <grep cmd> & shopt -y dotglobnur bequemer? Auf diese Weise müssen wir uns keine Gedanken über das Zurücksetzen machen
user606723

grep -Rin string .In den meisten Fällen ist die Verwendung wahrscheinlich einfacher . Ich benutze nur *, weil es natürlicher zu kommen scheint.
user606723

1
Wenn Sie rekursives Grep ausführen, können Sie einfach mit "." anstatt "*". Kein Dotglob erforderlich.
Michał Šrajer

1
vote up dies, ist eine Sache nicht in manpage erwähnen ist Rwird symbolische Links folgen, rnicht
HVNSweeting

12

Wenn Sie bereit sind, etwas Neues auszuprobieren, probieren Sie es aus ack. Der Befehl zum rekursiven Durchsuchen des aktuellen Verzeichnisses stringlautet:

ack string

Die Installation ist ganz einfach:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(Vorausgesetzt, Sie haben das Verzeichnis bereits ~/binund es befindet sich vorzugsweise in Ihrem PATH.)


2
Oder installiere einfach ack-grep (und füge alias ack = ack-grep zu deinem .bashrc hinzu)
markijbema

Was machen die letzten Parameter des chmodBefehls? Sind sie spezifisch für chmododer sind sie verwandt mit Bash (dem !#:3Teil)?
Elliott Darfink

@ElliottDarfink Das nutzt Bashs Verlaufsfunktion - !ist ein Ereignisbezeichner . Sie sind ziemlich mächtig, um Wiederholungen zu vermeiden. !#:3verweist bisher auf das dritte Token der Kommandozeile, also ~/bin/ackin diesem Fall.
Konrad Rudolph

4

Der Befehl rgrep ist für diesen Bedarf vorgesehen

Wenn nicht verfügbar, können Sie es so erhalten

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

Sie können Ihre Standard-Grep-Optionen wie oben beschrieben direkt festlegen.

Ich persönlich benutze

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

verwandtes thema : wie man rgrep immer mit farbe benutzt


rgrep wird durch das grep-Paket bereitgestellt, das standardmäßig in Ubuntu installiert ist.
Karl

2

Update 2:

Diese Befehlszeile verwendet findund grepbehebt das Problem:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> für farbige Ausgabe:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Beispiel:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Ein Beispiel für den folgenden Schnappschuss: snap1


Update 1:

Sie können versuchen, folgenden Code zu verwenden. als Funktion in Ihrem .bashrcoder .bash_aliasesoder in einem Skript:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Verwendungszweck: wherein /path/to/search/in/ searchkeyword

Beispiel:

$ wherein ~/Documents/ "hello world"

(Hinweis: Wie in den Kommentaren unten von @enzotib vorgeschlagen, funktioniert dies nicht mit Dateien / Verzeichnissen, in deren Namen Leerzeichen enthalten sind.)


Ursprünglicher Beitrag

So suchen Sie nach der Zeichenfolge und geben nur diese Zeile mit der Suchzeichenfolge aus:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

z.B:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

So zeigen Sie den Dateinamen an, der die Suchzeichenfolge enthält:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

z.B:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

Schlägt bei Dateinamen fehl, die Leerzeichen enthalten. Der Fehler wird durch die Tatsache verborgen, dass stderr nicht angezeigt wird.
Enzotib

@enzotib danke für den Hinweis .. das ist für die angegebene Funktion immer noch ungelöst .. Ich habe jedoch einen weiteren Einzeiler hinzugefügt ..
präzise

Jetzt ist die Antwort der von @dmityugov ähnlich.
Enzotib

Ja, aber in diesem Sinne sind die meisten Antworten auf dieser Seite, wenn Sie prüfen, ob sie in Bezug auf die Verwendung ähnlich sind grep, daneben die Teilmenge, die findmit grep... verwendet wird. Wenn Sie jedoch verschiedene Schalter und Optimierungen als eindeutige Antwort akzeptieren möchten, wahrscheinlich wird meins auch hier reinpassen .. oder unterscheiden sie sich? das letzte update macht was ich bei meiner suche möchte: dateinamen mit zeilen mit suchschlüssel und zeilen nr. Auch :) und farbige Ausgabe und Fehlerfilter für bessere Lesbarkeit ..
präzise

2

grep( GNU oder BSD )

Sie können das grepTool verwenden, um den aktuellen Ordner rekursiv mit -rParametern zu durchsuchen , z.

grep -r "pattern" .

Hinweis: -r- Durchsuchen Sie Unterverzeichnisse rekursiv.

Zum Durchsuchen bestimmter Dateien können Sie eine Globbing-Syntax verwenden, z.

grep "class foo" **/*.c

Hinweis: Mit der Globbing-Option ( **) werden alle Dateien mit einer bestimmten Erweiterung oder einem bestimmten Muster rekursiv durchsucht. Um diese Syntax zu aktivieren, führen: shopt -s globstar. Sie können auch **/*.*für alle Dateien (außer versteckt und ohne Erweiterung) oder jedes andere Muster verwenden.

Wenn Sie den Fehler haben, dass Ihr Argument zu lang ist, können Sie die Suche eingrenzen oder findstattdessen die folgende Syntax verwenden:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Alternativ verwenden ripgrep.

ripgrep

Wenn Sie an größeren Projekten oder großen Dateien arbeiten, sollten Sie ripgrepstattdessen Folgendes verwenden:

rg "pattern" .

Überprüfen Sie die Dokumente, Installationsschritte oder den Quellcode auf der GitHub-Projektseite .

Es ist viel schneller als jedes anderes Tool wie GNU / BSD grep , ucg, ag, sift, ack, ptoder ähnlich, da es auf der Spitze gebaut Rust Regex - Engine , die endlichen Automaten verwendet, SIMD und aggressive wörtliche Optimierungen sehr schnell zu machen suchen.

Es werden in .gitignoreDateien angegebene Ignoriermuster unterstützt , sodass ein einzelner Dateipfad gleichzeitig mit mehreren Glob-Mustern abgeglichen werden kann.


Sie können die allgemeinen Parameter verwenden, z.

  • -i - Unempfindliche Suche.
  • -I - Ignorieren Sie die Binärdateien.
  • -w - Suche nach ganzen Wörtern (im Gegensatz zur Teilwortübereinstimmung).
  • -n - Zeigen Sie die Zeile Ihres Spiels.
  • -C/ --context(eg -C5) - Vergrößert den Kontext, sodass Sie den umgebenden Code sehen.
  • --color=auto - Markieren Sie den passenden Text.
  • -H - Zeigt den Dateinamen an, in dem sich der Text befindet.
  • -c- Zeigt die Anzahl der übereinstimmenden Zeilen an. Kombinierbar mit -H.

1

Ich mache das mit xargs, einem sehr unterschätzten Befehl

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

Mit find ./ erhalten Sie eine rekursive Liste aller Dateien in einem aktuellen Ordner. Anschließend leiten Sie diese Liste an xargs weiter, das den Befehl grep für jede dieser Dateien ausführt


4
Wenn Sie xargsohne die -print0Option to findund die -0Option to nicht mehr weiterentwickeln xargs, schlägt dies bei Dateinamen fehl, die Leerzeichen enthalten.
Enzotib

@enzotib Ich habe die Antwort wie von Ihnen vorgeschlagen bearbeitet. danke
αғsнιη

1
@KasiyA: es ist jetzt ok, habe meine downvote entfernt.
Enzotib

0

Ich weiß, dass es hier viele Antworten gibt, aber hier ist eine Alternative, wenn Sie beim Durchsuchen der Dateien weitere Einschränkungen hinzufügen möchten:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

Dies funktioniert, weil grep0 zurückgegeben wird, wenn ein Ergebnis gefunden wurde, andernfalls 1. Zum Beispiel können Sie Dateien 1 MB groß finden und enthält etwas:

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

Für mehrere Anforderungen möchten Sie wahrscheinlich das Optimierer-Flag verwenden -O, das in GNU grep vorhanden ist.


0

Ein Skript (Find-In-Code) zum Suchen in C, CPP-Code:

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

Verwenden:

find-in-code "search string"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.