Zum Inhalt springen
Linux, DevOps & Systeme

Finde Text in Dateien unter Linux

Volltextsuche unter Linux: Text in Dateien finden mit grep, find und xargs, ripgrep als schnelle Alternative, zgrep für Archive und locate für Dateinamen.

Von DI Herwart Wermescher, MBA ↗

Immer wieder frage ich mich, in welcher der Konfigurationsdateien ein gewisser Text steht. Die Antwort liefert unter Linux fast immer grep, ergänzt um find, ripgrep oder locate. Hier die Werkzeuge, die ich täglich verwende, mit echten Befehlszeilen.

grep-Grundlagen

Der Standardaufruf für eine Volltextsuche über einen Verzeichnisbaum:

grep -r "suchbegriff" /pfad

Das durchsucht alle Dateien unterhalb von /pfad und gibt Dateiname und Fundzeile aus. Setz den Suchbegriff in Anführungszeichen, sobald Leerzeichen, Sternchen oder Dollarzeichen darin vorkommen, sonst frisst die Shell das Muster, bevor grep es sieht.

Ein typisches Beispiel aus meinem Alltag, die Suche nach einer Domain in allen vhosts:

grep -rn "wermescher.com" /etc/apache2/sites-available/

Die wichtigsten grep-Optionen

OptionWirkung
-rrekursiv durch alle Unterverzeichnisse
-iGroß- und Kleinschreibung ignorieren
-nZeilennummer des Treffers ausgeben
-lnur die Dateinamen ausgeben, nicht die Zeilen
-wnur ganze Wörter treffen
-cAnzahl der Treffer je Datei zählen
-vinvertieren, also alle Zeilen ohne Treffer
--includenur Dateien nach Muster durchsuchen, etwa --include='*.conf'
--excludeDateien nach Muster überspringen
--exclude-dirganze Verzeichnisse überspringen, etwa --exclude-dir=.git
-A nn Zeilen nach dem Treffer mit ausgeben
-B nn Zeilen vor dem Treffer mit ausgeben
-C nn Zeilen davor und danach
-Eerweiterte reguläre Ausdrücke
-FMuster als festen Text behandeln, keine Sonderzeichen

Kombiniert ergibt das kompakte Aufrufe. Alle .conf-Dateien nach well-known durchsuchen, Groß- und Kleinschreibung egal, mit Zeilennummer:

grep -rni --include='*.conf' "well-known" /etc/apache2/

Nur wissen, welche Dateien betroffen sind:

grep -rl "DocumentRoot" /etc/apache2/sites-available/

Kontext ist Gold wert, wenn Du einen Konfigurationsblock suchst und die umliegenden Direktiven brauchst:

grep -rn -C 5 "SSLCertificateFile" /etc/apache2/sites-available/

Und -v hilft beim Aufräumen, etwa um eine Konfigurationsdatei ohne Kommentare und Leerzeilen zu lesen:

grep -v -E '^\s*(#|$)' /etc/ssh/sshd_config

Statt eines festen Suchbegriffs kannst Du grep auch mit Mustern füttern — wie das geht, zeigt der Beitrag zu regulären Ausdrücken mit grep.

grep mit find und xargs kombinieren

grep -r reicht meistens. Sobald Du aber nach Dateieigenschaften filtern willst, also nach Alter, Größe, Besitzer oder Rechten, übernimmt find die Vorauswahl und übergibt an grep.

Die ursprüngliche Variante mit -exec:

cd /etc/apache2/sites-available/
find . -type f -name '*.conf' -exec grep -H 'well-known' {} \;

-H erzwingt die Ausgabe des Dateinamens, weil grep bei einer einzelnen Datei sonst nur die Zeile zeigt. Der Nachteil: -exec … \; startet für jede Datei einen eigenen grep-Prozess. Bei tausenden Dateien wird das spürbar langsam. Zwei schnellere Wege:

find . -type f -name '*.conf' -exec grep -Hn 'well-known' {} +
find . -type f -name '*.conf' -print0 | xargs -0 grep -Hn 'well-known'

Das + am Ende sammelt möglichst viele Dateien für einen Aufruf. Bei xargs sorgt das Paar -print0 und -0 dafür, dass Leerzeichen und Umlaute in Dateinamen nicht zum Problem werden.

Ein Beispiel mit echtem Mehrwert, alle in den letzten zwei Tagen geänderten Logdateien nach einer IP durchsuchen:

find /var/log -type f -name '*.log' -mtime -2 -print0 \
  | xargs -0 grep -Hn '203.0.113.'

Wie Du Dateien nach Größe eingrenzt, steht in Dateien ab einer bestimmten Größe finden.

ripgrep als schnelle Alternative

Für große Verzeichnisbäume und vor allem für Quellcode nutze ich ripgrep. Es durchsucht parallel, ist deutlich schneller als grep und überspringt von sich aus alles, was in einer .gitignore steht, dazu versteckte Dateien und Binärdateien.

Installation:

sudo apt install ripgrep

Der Aufruf ist kürzer, weil rekursiv und Zeilennummern die Voreinstellung sind:

rg "suchbegriff"
rg -i "TODO" src/
rg -t yaml "image:" 
rg --hidden --no-ignore "api_key"

-t filtert nach Dateityp, --hidden --no-ignore schaltet die Ignorierregeln ab, wenn Du wirklich alles sehen willst. Genau diese Voreinstellungen sind der Punkt: In einem Repository mit node_modules liefert grep -r tausende irrelevante Treffer, rg von Haus aus nur die aus dem eigenen Code.

Für die restlichen Fälle bleibt grep die richtige Wahl, weil es auf jedem System vorhanden ist. Auf einem fremden Server willst Du keine Pakete installieren, nur um eine Zeile zu suchen.

Suche in Archiven und komprimierten Dateien

Rotierte Logs liegen als .gz vor. Dafür gibt es die z-Varianten der üblichen Werkzeuge, die vor der Suche transparent entpacken:

zgrep "Fehler" /var/log/syslog.*.gz
zgrep -i "203.0.113.7" /var/log/apache2/access.log.*.gz

Passend dazu gibt es zcat, zless und zdiff. Für bzip2 heißen sie bzgrep, für xz xzgrep. Praktisch ist die Kombination aus beidem, um laufende und archivierte Logs in einem Rutsch zu prüfen:

grep -h "Fehler" /var/log/syslog; zgrep -h "Fehler" /var/log/syslog.*.gz

In tar-Archiven sucht grep nicht direkt. Dort listest Du entweder den Inhalt mit tar -tf oder entpackst nach stdout:

tar -xzOf backup.tar.gz | grep -a "suchbegriff"

Mehr zum Umgang mit Archiven findest Du unter zip, unzip und tar unter Linux.

Dateinamen statt Inhalt suchen

Manchmal suchst Du keine Textstelle, sondern die Datei selbst. Dafür ist find zuständig:

find /etc -type f -name 'ssl*.conf'
find /home -type f -iname '*.pdf'
find / -type f -name 'php.ini' 2>/dev/null

Das 2>/dev/null unterdrückt die Meldungen zu Verzeichnissen ohne Leserechte. find läuft dabei jedes Mal über das Dateisystem, was auf großen Platten dauert.

Schneller geht es mit einem Index. locate beziehungsweise dessen aktueller Nachfolger plocate fragt eine Datenbank ab und antwortet praktisch sofort:

sudo apt install plocate
sudo updatedb
locate php.ini
locate -i lebenslauf

Der Haken ist die Aktualität: Die Datenbank wird per Timer einmal täglich erneuert. Dateien, die Du gerade angelegt hast, findet locate erst nach einem manuellen sudo updatedb.

Volltextsuche über den ganzen Rechner

Eine echte Volltextsuche über alle Inhalte einer Platte ist etwas anderes als ein grep -r /. Letzteres liest bei jedem Aufruf sämtliche Dateien und dauert je nach Datenmenge Stunden. Für den einmaligen Fall geht das:

sudo grep -rIl "Vertragsnummer 4711" /home --exclude-dir={.cache,.git,node_modules}

-I überspringt Binärdateien, -l liefert nur die Dateinamen, und die ausgeschlossenen Verzeichnisse sparen den Großteil der Laufzeit.

Suchst Du hingegen regelmäßig in denselben Beständen, lohnt ein Index. Sinnvoll wird das ab etwa der Größenordnung eines gut gefüllten Home-Verzeichnisses oder eines Dokumentenarchivs, und immer dann, wenn Du auch in PDFs, Office-Dokumenten und Mails suchen willst. Ein Index extrahiert deren Text einmal und beantwortet Anfragen danach in Millisekunden.

Auf dem Desktop übernimmt das unter GNOME der Tracker, unter KDE Baloo, beides ist bereits aktiv. Für Server und größere Dokumentenbestände greife ich zu Recoll, das lokal indiziert und Formate wie PDF, ODT und DOCX mit abdeckt.

Die Faustregel, nach der ich entscheide: Einmalige Suchen, klar eingegrenzte Verzeichnisse und Quellcode gehören zu grep oder ripgrep. Wiederkehrende Suchen über viele Formate und große Bestände gehören in einen Index. Alles dazwischen erledigt locate für Namen und grep --include für Inhalte.

Verwandte Beiträge

Über diesen Blog

Ein Sammelsurium an Denkanstößen.

Hier sammle ich Wissen, Argumente und Links zu allem, was mich beschäftigt — von Technik über Küche bis Nachhaltigkeit. Beruflich berate ich zu Cybersecurity.