Nach Dateien und deren Inhalten zu suchen, gehört zum täglich Brot, sei es online oder auf dem lokalen PC. Unter unixoiden Betriebssystemen wie Linux findet man seit jeher mit GNU Find.
Apple nennt unter MacOS das zentrale Tool Finder, Microsoft liefert seine Betriebssysteme mit der Windows-Suche aus. Dass Windows nur sucht, statt wie MacOS zu finden, klingt beinahe nach einem Eingeständnis. Unter Unix erblickte 1974 das Werkzeug Find das Licht der Welt. Uns interessiert im Rahmen dieses Artikels nur dessen GNU-Implementierung. Ohne Argumente liefert der Aufruf »find« rekursiv sämtliche Dateien, Verzeichnisse, (Sym-)Links und so weiter unterhalb des aktuellen Verzeichnisses. Dasselbe klappt aber auch mit einer Pfadangabe. Ein Find-Aufruf direkt in »/var/log/« und das Kommando »find /var/log/« liefern also identische Ausgaben.
Filtern nach Typen
Um die Ergebnisse weiter einzugrenzen, bringt Find zahlreiche Filtermöglichkeiten mit. Der eingebaute Schalter »-type« erlaubt unter anderem, nach echten Dateien (»-type f«), nach Verzeichnissen (»-type d«) oder nach Links »-type l« zu suchen. Daneben gibt es noch weitere Typen, über die die Manpage Auskunft gibt.
Sehen wir uns ein konkretes Beispiel an: Das Kommando aus der ersten Zeile von Listing 1 erzeugt eine einfache Textdatei mit kurzem Inhalt. Sie erhält anschließend per Touch ein anderes Modifikationsdatum (Zeile 2). Darauf kommen wir später noch einmal zurück. Als Nächstes entsteht per Ln ein sogenannter Hardlink (Zeile 3). Hardlink und Originaldatei lassen sich nicht unterscheiden. Das liegt in ihrer Natur, denn sowohl der Link als auch die Originaldatei besitzen als Adresse denselben Inode im Dateisystem. Existiert zu einer Datei ein Hardlink, gilt der Dateiinhalt erst dann als gelöscht, wenn sowohl der Hardlink als auch die Datei nicht mehr existiert.
Listing 1
Filtern nach Typen
$ echo "Ich bin eine Textdatei." > test.txt $ touch -d '19991231' test.txt $ ln test.txt test.lnk $ ln -s test.txt test_symlink.lnk $ mkdir testdir
Das erklärt, warum Sie keine Hardlinks erzeugen können, die auf Dateien auf anderen Laufwerken oder Partitionen zeigen. So etwas funktioniert nur mit symbolischen Links, kurz Symlinks (Zeile 4). Damit verweisen Sie flexibel nicht nur auf Dateien, sondern außerdem auf Verzeichnisse und andere Dateisysteme. Dahinter steckt technisch gesehen nichts anderes als eine Art Textdatei, die einen Pfad enthält. Zu guter Letzt entsteht noch ein Verzeichnis (letzte Zeile).
Listen Sie nun den Verzeichnisinhalt mit »ls -li« auf (Abbildung 1), sehen Sie, dass sich »test.txt« und »test.lnk« praktisch nicht auseinanderhalten lassen. In der ersten Spalte steht die Inode-Nummer, die bei Link und Datei identisch ausfällt.
Nach diesen Vorarbeiten geht es an erste Experimente mit Find. Suchen Sie im aktuellen Verzeichnis (»./«) nach Dateien, nach Links und nach Verzeichnissen (Abbildung 2). Schon die Suche nach Dateien birgt eine Überraschung: Find betrachtet Hardlinks als Dateien. Damit ist klar, dass in unserem Beispiel eine Suche nach Links lediglich ein einziges Ergebnis liefern kann. Auch die Suche nach Verzeichnissen ergibt Unerwartetes: Find findet nicht nur das Verzeichnis »testdir/«, sondern ebenso das aktuelle Verzeichnis »./«.

Abbildung 2: Die Suche nach Dateien, Links und Verzeichnissen erbringt teils überraschende Ergebnisse.
Filtern nach Zeit
Jede Datei unter Linux trägt drei Zeitstempel: die Modification Time »MTIME«, die Access Time »ATIME« und die Change oder Creation Time »CTIME«.
»MTIME« gibt an, wann der Dateiinhalt zuletzt geändert wurde. Im Fall einer Log-Datei kann man davon ausgehen, dass sie sich recht häufig ändert. Möchten Sie wissen, wann eine Datei zuletzt gelesen wurde, ist »ATIME« Ihr Freund. Interessieren Sie sich dafür, wann die Metadaten einer Datei zuletzt modifiziert wurden, also Owner, Gruppe oder Berechtigungen, dann kommt »CTIME« ins Spiel.
Find gibt Ihnen mit den Schaltern »-mtime«, »-atime« und »-ctime« die korrespondierenden Filtermöglichkeiten an die Hand. Alle drei erwarten einen ganzzahligen Wert für das Alter in Tagen. Über ein vorgestelltes Pluszeichen geben Sie das Mindestalter an, über ein Minuszeichen das Höchstalter. Beim Filtern nach Zeiten beachtet Find nur ganze Perioden von 24 Stunden, angebrochene Tage ignoriert das Tool dementsprechend. Abbildung 3 zeigt einige Varianten.

Abbildung 3: Dateien, die innerhalb des letzten Monats geändert wurden (oben), auf die innerhalb der letzten 24 Stunden zugegriffen wurde (Mitte) und deren Metadaten vor mindestens einer Woche angepasst wurden (unten).
Finden und verarbeiten
Jeder Admin steht gelegentlich vor der Aufgabe, Eigentümer, Gruppen und deren Berechtigungen in ganzen Verzeichnisbäumen korrigieren zu müssen. Freilich könnten Sie das einfach per Chown und Chmod rekursiv korrigieren, etwa durch »chmod -R 750 Verzeichnis«. Das würde dann sicherstellen, dass Eigentümer und Gruppe entsprechende Rechte auf den Verzeichnisbaum besitzen. Allerdings hätten Sie dann auch jede enthaltene Datei als ausführbar für Eigentümer und Gruppe markiert (7=»rwx«, 5=»r-x«, 0=»—«). Das erweist sich nur in seltenen Fällen als sinnvoll. Um hier zwischen Verzeichnissen und Dateien zu unterscheiden, machen Sie sich die Stärken von Find zunutze: Mit der Option »-exec« führen Sie auf jeden Treffer ein bestimmtes Kommando aus.
Zuerst korrigieren Sie die Berechtigungen der Verzeichnisse, anschließend die der Dateien (Listing 2). Den auszuführenden Befehl (hier »chmod«) müssen Sie dabei terminieren, entweder durch ein Pluszeichen oder durch ein Semikolon. Bei Letzterem kommt Ihnen allerdings die Shell in die Quere. Für sie hat das Semikolon eine besondere Bedeutung: Es separiert Kommandos voneinander. Daher verschluckt die Bash den Strichpunkt, der so niemals Find erreicht. Um das zu verhindern, müssen Sie das Semikolon entweder per Backslash escapen oder in einfache Hochkommas stellen. Geschweifte Klammern sorgen dafür, dass Fundstellen inklusive Pfad an das externe Kommando übergeben werden.
Listing 2
Externe Kommandos
$ find . -type d -exec chmod 750 {} \;
$ find . -type f -exec chmod 640 {} +
Auf dieselbe Weise suchen Sie rekursiv nach Inhalten von Dateien. Zwar beherrscht Grep ebenfalls Rekursion, es vermag jedoch nicht weiter zu filtern. Es würde deshalb daran scheitern, ausschließlich Textdateien mit Größen unter 1 MByte, deren letzte Änderung drei Tage zurückliegt, nach Text zu durchsuchen. Mit Find ist das recht simpel (Listing 3).
Listing 3
Find-Grep-Kombi
$ find . -type f -size -1M \
-mtime +3 -name "*.txt" \
-exec grep SUCHTEXT {} \;
Fazit und Ausblick
Schon die hier vorgestellten grundlegenden Find-Optionen befähigen Sie, recht präzise die richtigen Dateien, Verzeichnisse und so weiter zu finden. Das volle Potenzial von Find ist damit aber noch längst nicht ausgeschöpft. Im zweiten Teil dieses Workshops beschäftigen wir uns mit den fortgeschrittenen Funktionen des Werkzeugs wie logischen Verknüpfungen und Pruning. (csi/jlu)





