Suchen und finden von Dateien und Inhalten
 

 

1. find - Suchfunktion für Dateien

2. grep - Suchfunktion in Dateien

3. Begriffe in Dateien finden mit find, xargs und grep

 

find

find = findet alle Dateien in Verzeichnissen auf die das Suchmuster zutrifft und gibt sie als Pfad aus.

Syntax = find [pfad] [expression] Suchmuster

wichtigste Expression: -name, -iname, -type
z.B.:
# find / -name messages
/var/admin/notify/messages
/var/log/messages

durchsucht das Wurzel-Verzeichnis (also das gesamte Verzeichnis) nach Dateien mit dem Namen messages.

# find /home -iname LiStE
/home/liste
/home/LISTE

durchsucht das /home-Verzeichnis nach "liste" und ignoriert (das i vor name) die Groß- und Kleinschreibung.

# find /home -type f
listet alle Dateien (-type f=vom Typ Files) im Verzeichnis /home auf, also keine Ordner!

Auch Wildcards funktionieren, allerdings kann es vorkommen, daß man diese vor der Shell mittels des Backslash verstecken muß. Ob es ohne die "maskierung" geht, muß man einfach ausprobieren.
# find /home -name brief\*
/home/briefkopf
/home/brieffreund

Eine der wichtigsten Optionen für find ist -xdev, da diese verhindert, daß auf eingehängten Dateisystemen (auf anderen Partitionen) gesucht wird.
# find / -xdev -iname *.conf
sucht im gesamten Verzeichnis außer in den eingehängten Partitionen nach allen Dateien mit der Endung .conf.

find kann nicht nur Dateien finden, sondern sie auch an andere Programme weitergeben.
# find . -name "*.wma" -exec ffmpeg -i {} {}.wav \;
sucht im aktuellen Verzeichnis nach Dateien mit der Endung .wma und übergibt die Suchbegriffe mittels der geschweiften Klammer dem Programm ffmpeg, welches sämtliche Dateien in das wav-Format konvertiert. Abgeschlossen werden muss der Befehl mit \; (Backslash und Semikolon). Möchte man vor der Ausführung des Befehls gefragt werden, um z.B. bei Löschaktionen nicht versehentlich falsche Dateien zu löschen, nimmt man statt -exec die Option -ok. Zum Beispiel löscht der folgende Befehl
# find /home/user/ -name "*.txt" -ok rm {} \;
erst dann die gefundenen Dateien, wenn man es bestätigt.


grep

grep = Durchsucht den Inhalt von Dateien und gibt alle Zeilen aus, auf die das Suchmuster paßt

Syntax= grep [options] Suchmuster [File]

grep eignet sich hervorragend für Pipelines und wird daher häufig mit dem
Pipe-Zeichen (|) verwendet:
# more /var/log/messages | grep runlevel
May 29 19:47:22 linux init: Switching to runlevel: 6.

more öffnet die Datei messages und übergibt sie an grep, welches nach dem Begriff "runlevel" sucht und die entsprechende Zeile in der Datei ausgibt.

# grep -2 runlevel /var/log/messages
listet alle Einträge in der Datei messages auf, die die Zeichenfolge "runlevel" enthalten inklusive der 2 vorhergenden und nächsten 2 folgenden Zeilen (-2).

grep arbeitet mit sogenannten regulären Ausdrücken. Als da wären:
. = der Punkt steht für ein beliebiges Zeichen (vergleichbar mit dem Wildcard-Ausdruck: ?).
* = Der Stern steht für eine beliebig häufige Wiederholung des vorhergenden Zeichens oder auch kein Zeichen! Ein Beispiel:
abc*de
paßt auf abccccccde oder auch abde.
Möchte man also das Wildcard Zeichen * als regulären Ausdruck, muß man
.* (Punkt-Stern) angeben, also steht .* für eine beliebige Anzahl von beliebigen Zeichen oder auch keines! Folglich steht ..* für beliebig viele Zeichen oder mindestens ein beliebiges Zeichen, z.B.
abc..*ef
paßt auf abcdef oder auch abcxyzef aber nicht auf abcef (fehlt ein Zeichen!).

Auch grep kann rekursiv Verzeichnisse durchsuchen mit Hilfe der Option -r. Also ist
# find /etc -type f | xargs grep eth0
gleichzusetzen mit
# grep -r eth0 /etc
Trotzdem hat die Pipe mit find einen unschlagbaren Vorteil: während grep das gesamte Verzeichnis durchsucht (sogar die Binär-Dateien!), kann man mittels find gezielt Dateien auswählen.
# grep -rl eth0 /etc
Mit der Option -l listet grep Dateien nur einmal auf in denen der Suchstring mehrmals vorkommt und auch nur den Dateinamen.
# grep -rw eth /etc
wir erinnern uns an die Option -w (ganzes Wort), also findet grep "eth=192.168.0.1" jedoch nicht "realeth", oder "ethconfig".


Begriffe in Dateien finden mit find, xargs und grep

# find /etc -type f | xargs grep eth0
find sucht im Verzeichnis /etc nur nach Dateien (-type=Suchtype, f=files) also listet find alle Dateien (keine Ordner!) auf, die es in dem Verzeichnis /etc samt Unterverzeichnissen findet und übergibt diese an xargs, welches das Kommando grep auf die gefundenen Dateien anwendet um nach der Zeichenfolge "eth0" in den Dateien zu suchen.

Optionen für grep:
-i Groß- und Kleinschreibung ignorieren
-l nur den Dateinamen ausgeben der das Suchwort enthält und die Suche in dieser Datei abbrechen -> so wird jede Datei die den Suchstring enthält nur einmal aufgelistet.
-w sucht nach "ganzen" Wörtern, also gibt nur Treffer aus, wenn der Suchstring "alleine" steht ohne andere Zeichen.

Es werden sämtliche Dateien aufgelistet in denen die Zeichenfolge eth0 vorkommt, egal ob davor oder dahinter Leerzeichen oder sonstige Zeichen sind, also auch
"1 eth0=" oder "interfaceeth0istokay". Will man nur die Zeichen am Zeilenanfang finden, muß ein ^ vorangestellt werden. Ein $ gilt für das Zeilenende.

Beispiele:
# find /etc -type f | xargs grep ^eth0
"1 eth0" wird nicht gefunden, aber "eth0 = 192.168.1.4" schon (Zeilenanfang!).

# find /etc -type f | xargs grep eth0$
"1 eth0" wird gefunden, aber "eth0 = 192.168.1.4" nicht (Zeilenende!).

# find /etc -type f | xargs grep '1 eth0'
Kommen Leerzeichen im Suchstring vor, muß er in doppelte oder einfache Anführungszeichen gesetzt werden. (Einfache sind zu bevorzugen, da doppelte für manche Sonderzeichen noch eine Sonderbedeutung haben, siehe hier).

# find /etc -type f | xargs grep \ eth0
\ maskiert das Leerzeichen, daher wird "1 eth0" und "2 eth0=192" gefunden, "eth0=192" jedoch nicht, da es am Zeilenanfang steht und daher kein Leerzeichen vor eth0 enthält.

# find /etc -type f | xargs grep -w if
Mit der Option -w sucht grep nach dem Suchstring als "ganzes" Wort, also ohne Zeichen davor oder dahinter und findet somit "if=192.168.0.1" (das = ist kein Zeichen von a-z und gilt daher nicht) aber nicht "ifconfig".

Kommen Leerzeichen in den gefundenen Dateien vor, kann es sein, daß eine Reihe von Fehlermeldungen entstehen, da xargs die gefundenen Dateien durch Leerzeichen getrennt an grep übergibt. So führt eine Datei wie "Datei 1.txt" zu einer Fehlermeldung, daß "Datei" und "1.txt" nicht gefunden wurden. Um dieses Verhalten zu unterbinden helfen die Optionen -print0 für find und -0 für xargs.
# find /etc -type f -print0 | xargs -0 grep network
-print0 hängt an die zeilenweise Ausgabe von find jeweils ein Null-Terminierungs-Zeichen an und mit der Option -0 nimmt xargs nicht mehr Leerzeichen als Trenner, sondern besagtes Null-Terminierungs-Zeichen. Da grep einen Auszug des Treffers aus jeder Datei ausgibt, kann es sehr schnell unübersichtlich werden. Möchte man lediglich wissen, in welchen Dateien der Suchbegriff vorkommt, hilft folgende Pipe:
# find /etc -type f -print0 | xargs -0 grep -c 'network' | grep ':[1-9]'
Mit der Option -c werden nur sämtliche Treffer des Suchbegriffs für alle gefundenen Dateien angezeigt. Leider damit auch die Dateien, in denen kein Treffer vorhanden ist. Mit dem zusätzlichen grep ':[1-9]' werden nur Dateien aufgelistet mit mindestens einem Treffer.

Zum Abschluß noch eine etwas längere Pipe um den Speicherplatzverbrauch sämtlicher Ordner in einem Verzeichis oder einer Partition anzeigen zu lassen.
# find . -type d | sed -e "s/\.\///" -e 's/^/"/' -e 's/$/"/' | xargs -I dummy du -sh dummy
Zuerst werden mit find alle Ordner gefunden (type d=directory). Anschließend wird mit sed der Punkt mit dem Schrägstrich vor jedem Ordner entfernt und jeweils ein Anführungszeichen am Anfang und am Ende eingefügt für eventuelle Leerzeichen in den Ordnernamen. Die in Anführungsstriche eingefaßten Ordnernamen werden an xargs übergeben, welches die Variable dummy generiert und die Ordnernamen an selbige übergibt. Mittels dieser Variable kann man den Befehl du ausführen, welcher den Speicherplatzverbrauch der betreffenden Ordner berechnet.