Dieser Artikel ist größtenteils für alle Ubuntu-Versionen gültig.
Das Kommandozeilenprogramm find findet Dateien mit bestimmten vorgebbaren Kriterien in ganzen Verzeichnisbäumen ab angegebenen Startpunkten. Dabei kann es die Suche auf vielfältige Weise filtern, z.B. nach Dateiname, -alter, -größe und die Suchergebnisse formatiert ausgeben und/oder weiter verarbeiten.
Da unter unixartigen Systemen der Leitsatz „Alles ist eine Datei“ gilt, werden auch Verzeichnisse und andere in der Dateihierarchie eingetragene Dateitypen (z.B. Sockets) gefunden. Der Einfachheit halber meint in diesem Artikel das Wort „Datei“ meistens jedes von find gefundene Ergebnis unabhängig von dessen konkretem Dateityp.
Das Programm find ist wegen seiner zahlreichen Suchkriterien sehr mächtig und daher fast immer das Mittel der Wahl, wenn es darum geht, auch Unterverzeichnisse zu durchsuchen bzw. eine Menge von über die Suchkriterien bestimmten Dateien zu bearbeiten. Wegen seiner Mächtigkeit kann es aber auch schwer anwendbar sein. In manchen Situationen kommt man daher mit anderen Methoden schneller oder einfacher zum Ziel:
Wenn man den Dateinamen genau kennt, kann locate eine bessere Wahl sein. Das Programm locate
arbeitet allerdings mit einem nur täglich aktualisierten Index und findet daher ganz frische Dateien nicht.
Für die spezielle Suche nach Programmen kann man which
oder whereis
benutzen:
Das Programm which
findet den Speicherort eines über die Umgebungsvariable PATH
auffindbaren Programms.
Das Programm whereis
findet ebenfalls den Speicherort und zusätzlich den Quelltext und die Manpages, sofern vorhanden.
Im aktuellen Verzeichnis, ohne Unterverzeichnisse zu berücksichtigen, kommt man mit automatischer Vervollständigung und den Jokerzeichen *
und ?
oft weiter, wenn man Namensbestandteile kennt. Manche Programme bieten auch von sich aus an, Unterverzeichnisse zu berücksichtigen, siehe ls und grep.
Wer lieber in der grafischen Oberfläche nach Dateien suchen möchte, kann eine Desktopsuchmaschine verwenden. Diese sind teilweise spezifisch für den jeweiligen Desktop und berücksichtigen bei der Suche auch die Meta-Daten der Dateien.
Das Programm ist in den offiziellen Paketquellen von Ubuntu enthalten und wird auf jedem System installiert.
findutils (Programme zum Suchen nach Dateien - find, xargs, aus main)
Befehl zum Installieren der Pakete:
sudo apt-get install findutils
Dieser Artikel beschreibt die vorstehende Version. Es gibt allerdings auch eine neue Implementierung namens rust-findutils, die experimentierfreudige Anwender optional aus universe installieren können und verspricht, das traditionelle find 1:1 zu ersetzen.
Im Terminal[1] verwendet man das Programm mit dieser generellen Syntax:
find OPTIONen STARTPUNKTe TESTs AKTIONen
Ein Aufruf kann ziemlich komplex werden; hier ein konkretes Beispiel:
find -P ~ -xdev -type f -printf '%s\t%k\t%p\n' | sort -g -r | head -n 5
In diesem Beispiel ist „-P
“ eine OPTION, „~
“ der STARTPUNKT, „-xdev -type f
“ sind die TESTs und „-printf '%s\t%k\t%p\n'
“ die AKTION. Es ist nicht unüblich, die Ausgabe von find per Pipe weiterzuleiten an andere Programme, wie auch in diesem Beispiel gezeigt. Das Beispiel ermittelt die 5 größten regulären Dateien im Homeverzeichnis des Benutzers, dabei werden symbolische Links und eingebundene Dateisysteme nicht berücksichtigt; weitere Erklärungen siehe späteren Abschnitt Beispiele.
OPTIONen ist eine möglicherweise leere Folge von Angaben nach Tabelle 1.
STARTPUNKTe ist eine möglicherweise leere Liste von Dateinamen. Das Programm prüft jeden Namen, ob eine Datei mit diesem Namen existiert und nimmt dann diese Datei als einen Startpunkt für seine Suche oder erzeugt anderenfalls eine Fehlermeldung, bearbeitet aber andere Namen in der Liste. Ein Startpunkt ist im Regelfall ein Ordner in der Dateihierarchie, andere Dateitypen sind möglich, aber selten sinnvoll. Bei Angabe mehrerer Startpunkte werden diese nacheinander abgearbeitet. Das Programm untersucht alle Dateien ab jedem angegebenen Startpunkt und bei Ordnern auch rekursiv alle enthaltenen Dateien. Wenn man keinen Startpunkt angibt, gilt das Verzeichnis „.“ als Startpunkt.
TESTs ist eine möglicherweise leere Folge von Suchkriterien nach Tabelle 2. Alle Tests werden mit „Und“ verknüpft, d.h. es werden nur die Dateinamen von Dateien, die alle Tests bestehen, an die AKTIONen weiter gegeben – diese Verknüpfung kann man wie unter Kombinationen beschrieben ändern. Wenn man keinen Test angibt, werden alle Dateien ausgewählt.
AKTIONen ist eine möglicherweise leere Folge von Operationen nach Tabelle 5, die an den über die Tests selektierten Dateien ausgeführt werden sollen – man kann z.B. Dateinamen listen, Dateien löschen oder Dateinamen als Argumente an beliebige andere Programme übergeben. Wenn man keine Aktion angibt, wird als Standardaktion -print
ausgeführt.
Tests und Aktionen kann man auch mischen. Das Programm optimiert die angegebene Reihenfolge in einer durch Optionen beeinflussbaren Weise.
Es sind außerdem unter Tests und Aktionen noch einige spezielle Angaben möglich, die die Dokumentation des Programms als "global options", "positional options" und als "operators" beschreibt und in diesem Artikel auszugsweise unter Tests mit besprochen werden, da sie wie diese angewendet werden. Diese speziellen Angaben modifizieren entweder generell die Arbeitsweise des Programms oder die Funktion einzelner Tests; ein Beispiel dafür ist -help
:
find -help
⚓︎ Weitere Details kann man dem Manual (Manpage) des Programms entnehmen:
Auf dem eigenen Rechner:
man find
oder Ubuntu Manuals im Internet zu find 🇬🇧
Noch weiter informativ sind
auf dem eigenen Rechner die Infoseiten zu find:
info find
und
die sehr ausführliche Seite zu findutils auf gnu.org 🇬🇧.
Das Programm durchläuft die Dateinamensbäume ab den Startpunkten als Wurzeln rekursiv und, sofern man das nicht selbst begrenzt, vollständig nach einer von zwei möglichen Strategien:
„Breite vor Tiefe“: Gefundene Ordner werden nach der Behandlung von regulären Dateien und anderen Dateitypen als letztes durchsucht.
„Tiefe vor Breite“: Gefundene Ordner werden sofort durchsucht, also vor regulären Dateien und anderen Dateitypen behandelt.
Bei jeden Aufruf von find wird die Suchstrategie einmalig vor dem Beginn der Suche durch Analyse der Kommandozeile bestimmt und dann nicht mehr verändert.
Die Auswahl der Strategie ändert nicht, was gefunden wird, sondern nur die Reihenfolge, in der es gefunden und ggf. gelistet wird. Vorgabe ist „Breite vor Tiefe“, sofern man weder bei Tests -depth
noch die Aktion -delete
angibt. Jedes dieser beiden Schlüsselworte aktiviert „Tiefe vor Breite“.
Tabelle 1: Optionen | |
Kriterium | Beschreibung |
-H -L -P | Diese Optionen schließen sich gegenseitig aus, d.h. wenn man mehrere angibt, wird nur die letzte Angabe wirksam. Wenn man keine angibt, gilt als Vorgabe -P .Diese Optionen bestimmen den Umgang des Programms mit Dateien vom Typ symbolischer Link, die mit -P stets ignoriert werden und mit -L stets berücksichtigt und verfolgt werden sowie mit -H manchmal beachtet werden. |
-D DEBUG-OPTS | DEBUG-OPTS ist eine mit Kommata getrennte Liste von einem oder mehreren möglichen Begriffen, die man sich mit find -D help |
-O0 oder-O1 | Diese beiden Optionen sind gleichwertig und -O1 ist die Vorgabe. Die Reihenfolge von Tests wird automatisch so optimiert, dass Filterungen nach Dateinamen zuerst erfolgen. |
-O2 | Zusätzlich zur ersten Stufe werden auch Filterungen nach dem Dateityp (Tests -type und -xtype ) so früh wie möglich, aber nach den Tests für Dateinamen ausgeführt. |
-O3 | Es werden zusätzlich zur zweiten Stufe weitere Optimierungen aktiviert. |
Soll auch in verlinkten Ordnern (sowohl absolut, als auch rekursiv) im angegebenen Suchpfad gesucht werden, so ist beim Programmaufruf ein -L
anzufügen. Dieses muss jedoch vor den Suchpfad:
find -L .
sucht im aktuellen Verzeichnis, folgt gefundenen symbolischen Links und schließt auch Funde aus verlinkten Verzeichnissen in das Ergebnis ein.
Startpunkte geben an, wo gesucht wird, nicht was gesucht wird. Ist keiner angegeben, wird im aktuellen Arbeitsverzeichnis gesucht. Startpunkte müssen nach Optionen und vor den ebenfalls optionalen Suchkriterien und Aktionen platziert werden. In den meisten Fällen wird es sich dabei um Verzeichnisse handeln, andere Dateitypen sind aber auch erlaubt. Wenn nicht die ganzen gegebenenfalls dort darunter liegenden Verzeichniszweige durchsucht werden sollen, kann die Durchsuchungstiefe mit zusätzlichen Suchkriterien begrenzt werden.
find
ist äquivalent zu:
find -P . -print
Das Programm sucht also im aktuellen Verzeichnis, ignoriert symbolische Links und findet dort alle Einträge, deren Dateinamen mit vollständigen Pfad ab Startpunkt ausgegeben wird. Dazu gehört auch der Hardlink „.“ im Startpunkt „.“ als Ordner.
find foo
setzt den Startpunkt auf den Eintrag foo im aktuellen Arbeitsverzeichnis, und sofern dieser Startpunkt existiert und ein Ordner ist, wird darin gesucht und die Namen aller darin enthaltenen Dateien werden gelistet.
find ../
sucht im übergeordneten Verzeichnis.
find /tmp
sucht im absolut angegebenen Verzeichnis /tmp.
find /tmp /boot
sucht in zwei Verzeichnissen, also sowohl in /tmp als auch in /boot.
find /
sucht ab dem Wurzelverzeichnis / das gesamte Dateisystem – was lange dauern kann.
cd ; find V*
wechselt ins Home-Verzeichnis und die aufrufende Shell wertet dort den Glob V*
aus. Normalerweise gibt es dort die Order Videos und Vorlagen und dann ist für find
der Aufruf äquivalent zu:
find -P Videos Vorlagen -print
Die beiden Startpunkte werden durchsucht und alle darin enthaltenen Einträge gelistet.
Beachte: Das Jokerzeichen *
wird hier von der aufrufenden Shell[2] und nicht von find ersetzt. In der Regel ist dies bei Startpunkten die sinnvolle Arbeitsweise. Das Programm find
kann aber bei Tests und bei Aktionen auch selber mit Jokerzeichen umgehen, die ihm dann aber quotiert oder maskiert übergeben werden müssen.
Tabelle 2: Ausgewählte Tests bzw. Suchkriterien | |
Kriterium | Beschreibung |
-name MUSTER | sucht Dateinamen, die dem Muster MUSTER entsprechen. MUSTER ist ein Shell-Glob, kann also Jokerzeichen wie „* “ und „? “ enthalten, die dann immer quotiert oder maskiert werden müssen, damit die aufrufende Shell sie nicht interpretiert. Beispiele: „\*.txt “ oder „'???.t*xt' “. MUSTER kann den Schrägstrich „/ “ nicht enthalten und -name untersucht nur den Eigennamen, nicht den Pfad zur Datei. |
-iname MUSTER | arbeitet wie -name , aber ohne Beachtung der Groß- und Kleinschreibung. |
-path MUSTER | arbeitet ähnlich wie -name , untersucht aber auch den Pfad zur Datei und MUSTER darf daher auch den Schrägstrich enthalten. |
-ipath MUSTER | arbeitet ähnlich wie path , aber ohne Beachtung der Groß- und Kleinschreibung. |
-regex REGEX -iregex REGEX | arbeiten ähnlich wie -path bzw. -ipath , aber das Suchmuster ist nicht als Shell-Glob, sondern als regulärer Ausdruck anzugeben. Es werden standardmäßig reguläre Ausdrücke mit der Syntax von Emacs erwartet, das kann man mit -regextype ändern. |
-type T | selektiert Dateien nach ihrem Typ. T ist ein Kennbuchstabe zur Angabe des Typs, dabei steht f (= file) für reguläre Dateien, d (= directory) für Verzeichnisse und l für symbolische Links; weitere siehe Dokumentation. Man kann für T auch eine mit Kommata getrennte Liste von Kennbuchstaben angeben, wenn man nach mehreren Typen gleichzeitig suchen will. |
-size N | selektiert Dateien nach ihrer Größe: N ist eine ganze Zahl mit optionalem Vorzeichen (- , keines, + ) und angehängtem Multiplikator (c für Byte, k für KiB (Kibibyte), M für MiB, G für GiB), z.B. -42k , 42k , +42k , 2M ) Syntaktisch ist der Multiplikator optional, jedoch wird in der Praxis immer einer verwendet, denn die Voreinstellung b für 512 Byte ist leider nicht praxisgerecht. Der wirksame Zahlenbereich ändert sich mit Vorzeichen und Multiplikator, d.h. 4096c ≠ 4k usw! Näheres siehe Größe und find rechnet seltsam. |
-empty | sucht leere Dateien inkl. Ordner, also solche ohne Inhalt. |
-Xtime N -Xmin N | selektieren Datei nach dem Zeitpunkt ihrer letzten Änderung oder Verwendung. X ∈ { a, c, m } bestimmt den abzufragenden Zeitstempel, N ist eine ganze Zahl mit optionalem Vorzeichen (- , keines, + ), aber ohne angehängten Multiplikator, weil sich dieser aus dem Namen des Tests ergibt. Details siehe Alter und find rechnet seltsam. |
-newer DATEI | sucht nach Dateien, deren Inhalt nach dem von DATEI verändert wurde. |
-cnewer DATEI | sucht nach Dateien, deren Verwaltungsdaten nach denen von DATEI verändert wurde. |
-newerXY DATEI | sucht nach Dateien, deren Zeitstempel X nach dem Zeitstempel Y von DATEI verändert wurde. X , Y ∈ { a, c, m } |
-newerXt ZEITSPEZ | sucht nach Dateien, deren Zeitstempel X nach der Zeitangabe ZEITSPEZ verändert wurde. Details siehe Text. |
-user BESITZER -group GRUPPE | sucht nur nach Dateien, die dem Benutzer BESITZER bzw. der Gruppe GRUPPE gehören. BESITZER bzw. GRUPPE kann ein Name oder eine numerische Kennung UID bzw. GID sein. |
-uid N -gid N | arbeitet ähnlich wir vorstehende Tests, jedoch muss man als N eine numerische Kennung UID bzw. GID mit optionalem Vorzeichen angeben. Damit kann man dann auch z.B. nach „alle Benutzer mit kleinerer UID als N“ suchen. |
-nouser | sucht nach Dateien, deren numerische Besitzer-Kennung keinem dem System bekannten Benutzer entspricht. |
-nogroup | sucht nach Dateien, deren numerische Gruppen-Kennung keiner dem System bekannten Gruppe entspricht. |
Es gibt einige Optionen, die wie Tests verwendet werden, aber dann nicht die einzelnen Dateien beurteilen, sondern die Suche generell modifizieren. Es ist besser, diese Optionen lt. folgender Tabelle 3a zum Beginn der Tests anzugeben, denn sonst meckert find eine Warnung, macht aber trotzdem das, was es für richtig hält und das ist möglicherweise nicht das, was der Bediener haben wollte. Außerdem gibt es als Tests geschriebene positionelle Optionen nach Tabelle 3b, welche die Arbeitsweise ihnen folgender Tests modifizieren.
Tabelle 3a: Globale Optionen | |
Kriterium | Beschreibung |
-help | zeigt eine Kurzanleitung des Programms. Es wird nicht gesucht. |
-maxdepth n | sucht ab dem Startpunkt nur n (ganze Zahl ≥ 0) Verzeichnisse tief. Bezeichnet dieser ein Verzeichnis – z.B. implizit das aktuelle Verzeichnis – zählen dessen Einträge schon zu Tiefe 1. |
-mindepth n | durchsucht zwar alles, ignoriert aber alle Dateien mit kleinerer Verzeichnistiefe als angegeben. |
-depth | sucht erst rekursiv im Inhalt der Verzeichnisse, bevor das Verzeichnis selbst untersucht wird. (Standard bei -delete Aktion) ▶ Suchstrategie |
-xdev -mount | Order von anderen eingebundenen Dateisystemen werden nicht durchsucht. Das bei GNU find veraltete Synonym -mount soll man vermeiden. |
Tabelle 3b: Positionelle Optionen | |
Kriterium | Beschreibung |
-daystart | misst für alle (!) darauf folgenden -Xtime - und -Xmin -Kriterien ab 00:00 h des aktuellen Tages, also ab Mitternacht. Einmal eingeschaltet, lässt sich dieser Modus nicht mehr ausschalten. |
-regextype TYPE | ändert für folgende Texts mit regex den Typ des regulären Ausdrucks. Zulässige Typen listet find -regextype ? |
Die in diesem und folgenden Kapiteln ab diesem Hinweis gezeigten Beispiele enthalten fast alle einen Punkt „.
“ nach dem Programmnamen. Das soll den Leser daran erinnern, dass an dieser Stelle von ihm ein selbst gewählter Startpunkt oder eine Folge von Startpunkten einzusetzen ist, ab dem/denen gesucht werden soll. Man kann allerdings die Befehle auch genau so wie gezeigt verwenden und sie arbeiten dann im aktuellen Arbeitsverzeichnis (working directory). Schließlich kann man den Punkt auch weglassen, weil find eine leere Folge von Startpunkten automatisch und stillschweigend durch den Punkt ersetzt.
find . -name hausarbeit.odt
sucht nach Dateien mit dem vollständigen Namen hausarbeit.odt.
find . -name "*.pdf"
sucht nach PDF-Dateien. Der Test -name
berücksichtigt die Groß-/Kleinschreibung, findet hier also keine Datei(en) mit Endung *.PDF.
find . -iname a\*.pdf
sucht nach .pdf- und .PDF-Dateien, die mit a
oder A
beginnen (ignoriert die Groß-/Kleinschreibung).
find . -name "katze.*"
findet katze.jpg, katze.png, katze.txt, katze.frisst_die_Maus usw.
find . -name "katze.??g"
findet katze.jpg, katze.png usw. (jedes Fragezeichen steht für ein einzelnes Zeichen).
find . -name "*foo*.*x*"
findet foo.x, afoo.x, foob.txt usw.
Will man die Suche auf bestimmte Pfade einschränken, kommt man mit -name
nicht weiter. Das Suchkriterium -path
ist hier die Lösung, denn es erlaubt die Verwendung des die Namen trennenden Schrägstrichs /
.
find . -path "*2013/J*"
findet ~/Bilder/2013/Juni und ~/Musik/2013/Juli, aber nicht ~/Dokumente/2013-Juni.
Pfade ausschließen:
find ~ -path ~/Dokumente -prune -or -path ~/Downloads -prune -or -iname "*.pdf" -print -or -iname "*.tif*" -print
findet alle PDF- und TIFF-Dateien im Homeverzeichnis außer die in ~/Dokumente/ und ~/Downloads/. Das explizite -print
ist nötig, da -prune
nicht nur die Suche im jeweiligen Pfad sondern auch die Ausgabe zunächst abbricht.
Nicht lesbare Pfade ausschließen (vermeidet zahlreiche Fehlermeldungen):
find / ! -readable -prune -o -name "*.desktop" -print
find . -type f
findet nur reguläre Dateien. Verzeichnisse, Sockets, etc. werden ausgelassen.
find . -type d
findet nur Verzeichnisse (Typ: directory).
Man kann nach Dateien suchen, die kleiner, exakt gleich oder größer als ein vorgebbarer Vergleichswert sind, dabei wird der Vergleichsoperator durch das Vorzeichen des Vergleichswertes bestimmt:
find . -size -4096c -ls
Mit dem Vorzeichen „-
“ werden alle Dateien gefunden, die kleiner als 4096 Byte bzw. 4 KibiByte sind.
find . -size 4096c -ls
Ohne Vorzeichen wird auf exakte Gleichheit geprüft.
find . -size +4096c -ls
Mit dem Vorzeichen „+
“ werden alle Dateien gefunden, die größer als 4096 Byte bzw. 4 KibiByte sind. Bei diesen Befehlen ist die Angabe des Multiplikators „c
“ wichtig, denn sonst rechnet find seltsam. „c
“ bedeutet character
, welche früher 1 Byte belegten (b
ist schon für die Maßeinheit Block (= 512 Bytes) vergeben). Mittels dem zusätzlichen -ls
lässt sich die Größe der gefundenen Dateien überprüfen. Deswegen wird es hier, vor den anderen Aktionen, erwähnt.
Vorgenannte Befehle funktionieren mit jeder Anzahl von Bytes. Bei großen Schwellen kann man auch die Multiplikatoren k
für Kibibytes (1024), M
für Mebibytes (10242) oder G
für Gibibytes (10243) angeben, wegen der ungewöhnlichen Rechenweise sollte man das nur in folgender Art und Weise tun:
find . -size +4096c -ls
bzw.
find . -size +4k -ls
sucht Dateien größer (>
) 4kiB, also ab 4097 Byte.
find . ! -size +4k -ls
sucht Dateien bis maximal (≤
) 4kiB. Der Operator !
wird unten erklärt.
Man schreibe also numerische Angaben niemals ohne Multiplikator und immer
entweder mit beliebigem Vorzeichen und mit Multiplikator c
oder mit dem Vorzeichen +
und beliebigem Multiplikator.
Die Tests -Xtime
, Xmin
, -newer
, -Xnewer
sowie -newerXt
und -newerXY
(mit X, Y ∈ { a, c, m }) vergleichen einen Zeitstempel der untersuchten Datei mit dem aktuellen Zeitpunkt, Mitternacht oder einem Zeitstempel einer Referenzdatei. An der Stelle X
ist der Kennbuchstabe des zu untersuchenden Zeitstempels einzusetzen:
m
für mtime (modification time), d.h. Zeitpunkt der letzten Änderung des Dateiinhalts.
c
für ctime (changed time), d.h. Zeitpunkt der letzten Änderung der Verwaltungsdaten der Datei, dazu gehören Dateiname, Größe, Besitzer, Dateiberechtigungen, Zeitstempel und ähnliche Daten.
a
für atime (access time, Zugriff), d.h. Zeitpunkt des letzten Lesens des Dateiinhalts. Eine Dateiauflistung selbst ist damit nicht gemeint. Bei Bilddateien z.B. zählt aber die Vorschaufunktion eines grafischen Dateimanagers oder das Auslesen der Bildeigenschaften bereits als Zugriff. Die Zugriffszeit wird in der Regel erst bei mehr als 24 h Abweichung oder wenn sie älter als die letzte Änderung der Datei ist, also nicht bei jedem Lesen, aktualisiert (wenn das Dateisystem nicht mit vom Standard abweichenden zusätzlichen Optionen eingebunden ist). Man kann auch bei der Einbindung vorgeben, dass atime gar nicht gepflegt wird und dann kann der Test -atime
von find falsche Ergebnisse liefern und der Test -amin
wird sehr wahrscheinlich falsche Resultate liefern.
Der Linux Kernel unterstützt vier Zeitstempel, das Programm find kann aber mit dem von POSIX nicht definiertem Zeitstempel btime (für birth, Geburt, auch creation time) nicht umgehen. Lediglich für die Tests -newerXY
ist eine Unterstützung angedacht, aber in GNU find für Linux bisher nicht implementiert.
Bei -Xtime
und -Xmin
gibt, ähnlich wie bei der Größe, das Vorzeichen des Vergleichswertes an, ob man auf älter (+
), gleichaltrig oder jünger (-
) prüfen will. Die Tests -Xtime
verwenden als Maßeinheit immer Tag im Sinne einer Zeitspanne vor 24 Stunden, nicht im Sinne von Kalendertag, und die Tests -Xmin
verwenden Minute. Wie bei den Test auf Größe gilt auch hier: find rechnet seltsam mit den Vergleichswerten.
find . -mtime -100 -ls
sucht nach Dateien, deren Inhalt innerhalb der letzten 2400 Stunden geändert wurde bzw. in diesem Sinne jünger als 100 Tage sind.
find . -mtime 100 -ls
sucht nach Dateien, die mindestens 2400 Stunden alt, aber jünger als 2024 Stunden sind.
find . -mtime +100 -ls
sucht nach Dateien, deren Inhalt vor mehr als 2424 Stunden geändert wurde bzw. in diesem Sinne älter als 100 Tage sind.
Diese Befehle und auch ihre Pendants mit atime
und ctime
können den Bediener verwirren. In der Praxis justiert man mit -daystart
den zeitlichen Bezugspunkt auf den Beginn (Mitternacht) des aktuellen Tages, arbeitet damit effektiv doch mit Kalendertagen und kann dann (und sollte nur!) solche Befehle verwenden:
find . -daystart ! -mtime +0 -ls
zeigt nur Dateien, die heute (=0) geändert wurden.
find . -daystart ! -mtime +1 -ls
zeigt nur Dateien, die gestern (=1) oder heute geändert wurden.
find . -daystart ! -mtime +2 -ls
zeigt nur Dateien, die vorgestern (=2), gestern oder heute geändert wurden.
find . -daystart ! -mtime +N -ls
zeigt nur Dateien, die in den zurückliegenden N Kalendertagen bis einschließlich heute geändert wurden.
Die Tests-Xmin
arbeiten mit zeitlicher Auflösung von Minuten:
Eine vor dem Test notierte Angabe -daystart
wirkt auch unwiderruflich auf späteres -Xmin
!
find . ! -cmin +60 -ls
zeigt nur Dateien, die in der letzten Stunde verändert wurden. Dies betrifft auch inhaltliche Änderungen, denn eine Aktualisierung des Zeitstempels mtime ist eine Änderung in den Verwaltungsdaten, die eine Aktualisierung des Zeitstempels ctime erzwingt.
find . ! -mmin +60 -ls
zeigt nur Dateien, die in der letzten Stunde inhaltlich verändert wurden.
find . ! -amin +60 -ls
würde die Dateien anzeigen, die in der letzten Stunde inhaltlich gelesen wurden, sofern man im Dateisystem die minütliche Pflege des Zeitstempels atime aktiviert hätte und das auch bei der Einbindung berücksichtigt hätte. In der Regel trifft das aber nicht zu und manche Typen von Dateisystemen können atime gar nicht mit minütlicher Auflösung speichern. (Hinweis: Die Aussagekraft der Datei-Zugriffszeit ist stark von den Einhängeoptionen atime
, noatime
und relatime
abhängig.)
⚓︎
Die Tests -newer
und Varianten bieten eine mehr dem natürlichen Sprachgebrauch entsprechende Syntax und Semantik:
Im Vergleich zu einer bestimmten Datei
find . -cnewer /tmp/referenz
sucht nach Dateien, deren Name oder Status nach der Änderungszeit der Referenzdatei geändert wurden. Mit
touch --date='2004-02-29 15:00' /tmp/referenz`
erstellt man sich eine Referenzdatei, wenn man keine hat.
Der Test -newer
beschränkt das auf inhaltliche Änderungen, macht also das, was man von einem Test -mnewer
erwarten würde, den es aber unter diesem Namen nicht gibt.
Es gibt auch einen Test -anewer
mit denselben Einschränkungen wie -atime
und -amin
.
-newercc
ist ein alternativer Name für -cnewer
, und -newermm
ist ein alternativer Name für -newer
. Man kann aber in -newerXY
auch mit X ≠ Y unterschiedliche Arten von Zeitstempeln vergleichen.
⚓︎
Die Tests -newerct
und newermt
sind von praktischem Wert, da sie als Vergleichswert auch umgangssprachliche Formulierungen ermöglichen, beispielsweise:
find . -newerct '0000'
findet alle ab Beginn des heutigen Tages geänderten Dateien.
find . -newerct '0000 1 day ago'
findet alle gestern oder heute geänderten Dateien.
find . -newerct '12 hours ago'
findet alle in den letzten 12 Stunden geänderten Dateien.
Für den Vergleichswert ist alles zulässig, was auch date für seine Option „-d
“ akzeptieren würde, in dieser Sprache ist 0000
eine Schreibweise für Mitternacht.
Einige ausgewählte Beispiele:
Alle Dateien des Benutzers klaus:
find / -user klaus
Der Benutzer kann mit seinem Anmeldenamen oder als numerische Benutzerkennung UID angegeben werden. Da dieser Befehl die gesamte Dateihierarchie durchsucht, ist sinnvoll, ihn mit sudo zu verwenden.
Alle Dateien im eigenen persönliche Verzeichnis, die Fremden gehören:
find ~ ! -user $USER -ls
Diese Liste sollte leer sein.
Leere Verzeichnisse und Dateien:
find . -empty
Leere reguläre Dateien haben die Größe 0 und können daher auch über -size
gefunden werden, aber Ordner, auch leere, haben niemals die Größe 0, sondern belegen immer mindestens 1 Cluster (oft: 4kiB), der zur Speicherung der Namen der Dateien verwendet wird, die im Ordner liegen. Auch diese Liste ist niemals leer, sondern enthält immer die Namen „.
“ und „..
“. Für diesen Test gelten Ordner als leer, wenn sie nichts weiteres enthalten.
Verzeichnistiefe begrenzen:
find . -maxdepth 3
steigt bei der Suche nur 3 Verzeichnisebenen herab.
find . -mindepth 1
durchsucht die Startpunkte, liefert sie aber nicht als Treffer – hier das aktuelle Verzeichnis.
(Dieses Kapitel kann man beim ersten Lesen überschlagen. Es enthält Hintergrundinformationen und Begründungen für praktische Regeln.)
Numerische Angaben für find gehorchen nicht der naiven Erwartung! Für find bedeuten beispielsweise die Angaben 4096c
und 4k
nicht dieselbe Größe, und die Angabe 4096
(ohne Multiplikator) selektiert per Vorgabe den Multiplikator b
alias 512 Byte, und find versteht deshalb 4096 als 2 Mebibyte bzw. 2095104 Byte.
Der von find verwendete Algorithmus berechnet zunächst aus der zu prüfenden Zahl (z.B. die Größe einer Datei) Z und dem Wert des geltenden Multiplikators M die Hilfswerte „Z \ M
“ (ganze Zahl) und „Z mod M
“.
Anschließend wird ein Testwert V ermittelt: Wenn „Z mod M = 0
“, also wenn „Z / M
“ ganzzahlig wäre, dann wird „V = Z \ M
“ gesetzt, und anderenfalls wird aufgerundet zu „V = 1 + Z \ M
“.
Der so ermittelte ganzzahlige Testwert V
wird dann mit dem Absolutwert der ganzen Zahl aus dem Vergleichswert N
verglichen.
Bei der Suche nach Dateien kleiner als 4096 Byte ergeben sich beispielsweise die Rechenergebnisse lt. folgender Tabelle.
Tabelle 3c?: Rechenbeispiele | ||||||||
Test | N | M | Z | Z \ M | Z mod M = 0 | V | Vergleich | naive Erwartung |
-size -4096c | 4096 | c ≙ 1 | 4095 | 4095 | ja | 4095 | 4095 < 4096 | erfüllt |
-size -4096c | 4096 | c ≙ 1 | 4096 | 4096 | ja | 4096 | 4096 < 4096 | |
-size -4096c | 4096 | c ≙ 1 | 4097 | 4097 | ja | 4097 | 4097 < 4096 | |
-size -4096 | 4096 | b ≙ 512 | 3584 | 7 | ja | 7 | 7 < 4096 | zufällig erfüllt |
-size -4096 | 4096 | b ≙ 512 | 4095 | 7 | nein | 8 | 8 < 4096 | |
-size -4096 | 4096 | b ≙ 512 | 4096 | 8 | ja | 8 | 8 < 4096 | nicht erfüllt |
-size -4096 | 4096 | b ≙ 512 | 4097 | 8 | nein | 9 | 8 < 4096 | |
-size -4k | 4096 | k ≙ 1024 | 3072 | 3 | ja | 3 | 3 < 4 | erfüllt |
-size -4k | 4096 | k ≙ 1024 | 4095 | 3 | nein | 4 | 4 < 4 | nicht erfüllt |
-size -4k | 4096 | k ≙ 1024 | 4096 | 4 | ja | 4 | 4 < 4 | erfüllt |
-size -4k | 4096 | k ≙ 1024 | 4097 | 4 | nein | 5 | 5 < 4 |
Auch bei Größentests auf „exakte“ Gleichheit (Vergleichswert ohne Vorzeichen) gibt es wegen der Blockarithmetik von find der naiven Erwartung ähnlich widersprechende Ergebnisse (hier nicht gezeigt). Lediglich bei Größentests auf „größer als“ entsprechen die Rechenkünste von find der naiven Erwartung.
Daraus ergeben sich für die Praxis folgende Ratschläge:
Vergleichsgrößen immer mit Multiplikator angeben. Wenn es Probleme mit der Suche nach Größe gibt, dann wahrscheinlich, weil man c
, k
, M
oder G
vergessen hast.
Nach Möglichkeit nur Tests auf „größer“ verwenden (Vergleichswert mit Vorzeichen „+
“); eine Negation des Tests mit „!
“ ergibt dann einen Test auf „kleiner oder gleich“.
Wenn man Vergleichswerte ohne Vorzeichen oder mit dem Vorzeichen „-
“ verwenden will, verwende man als Multiplikator c
.
Vorstehende Ausführungen und Regeln für die Praxis gelten neben den Tests auf Größe auch für alle weiteren, die eine numerische Angabe erwarten, insbesondere bei den Tests auf Alter. Auch hier bevorzuge man Tests auf „später als“, angegeben durch das Vorzeichen „+
“ oder Namensbestandteil newer
.
Die Gesamtheit aller Tests und Aktionen bildet den in der Dokumentation so genannten Ausdruck (expression), in dem standardmäßig der Operator „Und“ die einzelnen Komponenten miteinander verbindet. Möglich sind aber auch andere Operatoren gemäß folgender Tabelle.
Tabelle 4: Operatoren | |
Operator | Beschreibung |
(Leerraum) | Durch Leerraum verbundene Tests bzw. Aktionen werden mit -a verbunden. |
-a -and | Konjunktion („Und“): Beide Tests müssen bestanden werden, oder der Dateiname gehört nicht mehr zum Arbeitsergebnis. |
-o -or | Disjunktion („Oder“): Die Datei muss mindestens einen, darf aber auch beide Tests bestehen, oder ihr Dateiname wird aus dem Arbeitsergebnis entfernt. |
-not ! | Negation: Der Dateiname wird aus dem Arbeitsergebnis entfernt, wenn die Datei den Test besteht. |
, | Listenbearbeitung: In Konstrukten wie z.B. „A , B , C “ werden die Komponenten sequenziell und einzeln bearbeitet, und die Arbeitsergebnisse außer dem letzten (also im Beispiel das von C ) werden verworfen. |
(In der Tabelle sind die Schreibweisen nach POSIX fett dargestellt, die anderen sind in der GNU-Variante von find Synonyme dazu.)
Die übliche Rangfolge der Operatoren wird beachtet: Negation bindet stärker als Und; Und bindet stärker als Oder. Wenn man etwas anderes will, muss man selber Klammern ()
verwenden, diese sind als Sonderzeichen der Shell bei ihrer Verwendung im Ausdruck für find immer zu quotieren oder zu maskieren.
Standard: Und-Kombination; die Funde müssen alle Kriterien erfüllen
find . -mindepth 3 -maxdepth 5
sucht von Verzeichnistiefe 3 bis 5.
Weiteres Beispiel der Und-Kombination
find . -mindepth 3 -type f -name "*.avi" -size +5M
beginnt die Suche in Verzeichnistiefe 3 und findet nur reguläre Dateien, die die Endung .avi
haben und größer als 5 MiB sind.
Man kann die Suchoptionen aber auch per Oder verknüpfen oder die Negation eines Tests bilden:
Negation:
find . ! -name "*.avi" -not -name "*.mp*g"
sucht Dateien die weder die Dateiendung avi
noch mpg
oder mpeg
haben. Das Ausrufezeichen und -not
sind gleichbedeutend.
Oder-Kombination
find . -name "susi.*" -or -name "susanne.*"
sucht Dateien die mit susi.
ober susanne.
beginnen.
Bei umfangreichen Kombinationen kann eine Klammerung erforderlich sein, um das gewünschte Resultat zu erhalten:
Ohne Klammern wird in
find . -name "susi.*" -or -name "susanne.*" -name "*.txt"
erst die Verbindung mit UND gebildet, also susanne.*
und *.txt
, danach erst ODER mit susi.*
. Auch susi.png würde also gefunden.
Mit Klammern wird jetzt in
find . \( -name "susi.*" -or -name "susanne.*" \) -name "*.txt"
für alle Dateien gefordert, dass diese auf .txt
enden. Klammern müssen maskiert oder quotiert sowie mit Leerzeichen isoliert werden.
Auch die Aktionen werden über Operatoren mit Tests verbunden, was manch überraschendes Ergebnis erzeugt. In einem Ordner mit diesen Dateien:
find .
. ./susanne.png ./susi.txt ./tusnelda.txt ./tusnelda.png ./susi.png ./susanne.txt
ergibt
find . -name 'susi*' -o -name 'susan*' -print
dieses Ergebnis:
./susanne.png ./susanne.txt
susi
wurde also nicht gefunden, obwohl genau das beabsichtigt war. Erst wenn man sich erinnert, dass der Leerraum für „Und“ steht, sowie dass „Und“ stärker bindet als „Oder“, erkennt man die Übereinstimmung der Eingabe mit deren ausführlicheren Schreibweisen:
find . -name 'susi*' -o -name 'susan*' -print find . -name 'susi*' -o -name 'susan*' -a -print find . -name 'susi*' -o \( -name 'susan*' -a -print \)
bedeuten alle dasselbe: Dem Muster susan*
entsprechende Dateinamen werden gesucht und ausgegeben; nach dem Muster susi*
wird ebenfalls gesucht, aber die Funde werden nicht ausgegeben, weil ein automatisches -print
nicht erfolgt wenn man selber eine Aktion wie -print
angibt.
Auf ein vorläufiges oder auf das endgültige Suchergebnis kann man eine oder mehrere Aktionen nach folgender Tabelle anwenden; insbesondere kann man auch -exec
mehrfach verwenden – meistens ist aber in solchen Situationen ein Skript zweckmäßiger. Auf das endgültige Suchergebnis wird automatisch -print
angewendet, sofern man nicht eine eine Aktion aus folgender Tabelle angibt.
Tabelle 5: Aktionen | |
Aktion | Beschreibung |
-print | erzwingt die zeilenweise Ausgabe von Eigenname mit Pfad jeder gefunden Datei. |
-print0 | gibt die Dateinamen wie -print aus, trennt diese aber durch ASCII NUL statt durch Zeilenvorschub (ASCII LF). |
-printf FORMAT | arbeitet wie print , wobei man das Ausgabeformat über FORMAT selber bestimmen kann. Die Möglichkeiten entsprechen weitgehend dem üblichen printf und sind in der Dokumentation beschrieben. In der Regel wird FORMAT immer mit einem Zeilenende „\n “ beendet. |
-fprint DATEINAME -fprint0 DATEINAME -fprintf DATEINAME FORMAT -fls DATEINAME | arbeitet wie die entsprechende Aktion ohne führendes f, gibt die gefunden Dateinamen aber nicht auf die Standardausgabe (Bildschirm) aus, sondern schreibt diese in die als DATEINAME benannte Datei, die ggf. gelöscht oder neu angelegt wird. |
-ls | zeigt die Dateinamen der selektierten Dateien wie der Befehl ls -dils . |
-prune | verwirft das bisherige Arbeitsergebnis. |
-quit | beendet das Programm. Das kann sinnvoll sein, nachdem gefunden wurde, was gesucht wurde. |
-delete | löscht die gefundenen regulären Dateien und leere Verzeichnisse. |
-exec KOMMANDO ; | wendet auf jeden gefundenen Dateinamen einzeln KOMMANDO (= ein Programm mit optionalen Argumenten) an. Nach einem Argument -exec im Aufruf müssen noch mindestens 2 weitere Argumente folgen. Aus dem ersten und allen weiteren Argumenten, die nicht das Semikolon „; “ sind, wird ein Programmaufruf mit Name und Argumenten erstellt, dabei wird das spezielle Argument „{} “ von find durch den gefundenen Dateinamen (Eigenname mit Pfad) ersetzt. Das erste Semikolon beendet die Konstruktion des Programmaufrufs. Damit es nicht unbeabsichtigt von der aufrufenden Shell interpretiert wird, muss es immer quotiert oder maskiert werden. |
-exec KOMMANDO {} + | Wendet auf die Gesamtheit aller Funde einmalig KOMMANDO an. Es werden nach -exec noch mindestens 3 weitere Argumente benötigt, davon muss das letzte den Wert „+ “ haben und der vorletzte den Wert „{} “ und diese müssen immer quotiert oder maskiert notiert werden, damit sie nicht von der aufrufenden Shell interpretiert werden. |
-ok … | Statt -exec kann man auch -ok mit derselben Syntax und Semantik für beide Aufrufformen verwenden, lediglich mit folgendem kleinen Unterschied: Mit -ok muss der Bediener vor der tatsächlichen Ausführung von KOMMAND den Aufruf bestätigen. |
-execdir … -okdir … | arbeiten weitgehend wie ihre Pendants ohne angehängtes dir , lediglich mit diesem Unterschied: Die Aktionen ohne angehängtem dir starten KOMMANDO in dem Arbeitsverzeichnis, in dem auch das aufgerufene Programm find aufgerufen wurde. execdir und okdir starten KOMMANDO in dem Ordner, welcher auch die gefundenen Dateien enthält. |
Ohne weitere Angaben gibt find nur die Namen der gefundenen Dateien mit Pfad aus:
find /boot/grub/ -name "he*"
/boot/grub/hexdump.mod /boot/grub/hello.mod /boot/grub/help.mod
Wie bereits weiter oben erwähnt kann man mit -ls
eine detailliertere Ausgabe erzeugen:
find /boot/grub/ -name "he*" -ls
168624 4 -rw-r--r-- 1 root root 3196 Jan 13 17:08 /boot/grub/hexdump.mod 168603 4 -rw-r--r-- 1 root root 1308 Jan 13 17:08 /boot/grub/hello.mod 168623 4 -rw-r--r-- 1 root root 2200 Jan 13 17:08 /boot/grub/help.mod
Wer die Ausgabe von find noch nach eigenen Vorstellungen gestalten möchte, verwende -printf
. Man vergleiche die Ausgaben dieser beiden Befehle (▶ Dokumentation):
find . -maxdepth 1 -type f -print
find . -maxdepth 1 -type f -printf '%P\n'
Eine etwas kritische Angelegenheit ist das Löschen mit der Aktion -delete
.
Da find auch Unterverzeichnisse durchsucht, sollte mit dieser Aktion vorsichtig umgegangen werden. Mit find gelöschte Dateien landen nicht im Papierkorb und können nicht wieder hergestellt werden. Man sollte -delete
immer nur als letztes Wort des Aufrufs verwenden.
Der Verwendung sollte ein Test ohne -delete
voraus gehen, um sicher zu gehen, nicht zu viele Dateien zu löschen. Für diesen Test ersetzt man in dem beabsichtigten Aufruf -delete
durch -print
und fügt die globale Option -depth
hinzu:
Aus dem beabsichtigten Befehl
find OPTIONen STARTPUNKTe TESTs AKTIONen -delete
macht man also zunächst für den Test:
find OPTIONen STARTPUNKTe -depth TESTs AKTIONen -print
Gegenbeispiel:
Der folgende Aufruf löscht den kompletten Inhalt des Ordners /home/ottifant/:
find /home/ottifant/ -delete -name Cache # falsch!
Mit -exec
und dessen Varianten kann man ein beliebiges Programm oder auch ein ausführbares Skript auf jeden Fund anwenden:
Die Anzahl der Zeilen in Textdateien findet man mit wc -l DATEI
; kombiniert mit find sieht das so aus:
find . -name "*.py" -exec wc -l {} \;
10 ./abc.py 6 ./x/date-form.py 102 ./x/download.py
Das Kommando wc -l
(Zeilen zählen) wird auf jede gefundene Datei angewendet. Die geschweiften Klammern werden durch die von find
gefundenen Namen ersetzt. Das Ende der Programmaufrufs muss mit einem Semikolon angezeigt werden. Damit das Semikolon nicht von der Shell interpretiert wird, muss man es mit einem Backslash maskieren oder in Anführungszeichen setzen.
Als Parameter für -exec
verschluckte Ausgabe von find wieder sichtbar machen
find tmp -name "a" -exec touch {} \; -print
./tmp/a ./tmp/a/a ./tmp/a/a/a
Weil touch nichts ausgibt und man dann deshalb keine Kontrolle darüber hat, was getan wurde, erhält man diese so über die -print
-Ausgabe von find.
Oft empfiehlt sich -execdir
statt -exec
find . -type d -execdir tar -cjf archiv.tar.bz2 {} \;
-execdir
führt das Kommando aus dem Verzeichnis heraus aus, in dem die Datei gefunden wird. So wird also für jedes Verzeichnis ein archiv.tar.bz2 vor Ort angelegt. Mit einem einfachen -exec
würde für jedes Verzeichnis ein Archiv im aktuellen Verzeichnis angelegt, d.h. das Archiv immer wieder überschrieben, so dass am Ende nur ein Archiv mit den Ergebnissen der letzten Ausführung von tar verbliebe.
Anstatt -exec
bzw. -execdir
kann man auch -ok
bzw. -okdir
verwenden
find -name "*pdf" -okdir xpdf {} \;
fragt vor jeder Datei nach, ob man wirklich die Aktion ausführen möchte.
Gesammelte Ausführung mit +
Beendet man ein Kommando mit Plus +
statt mit Semikolon ;
, so werden mehrere, u.U. alle Funde auf einen Rutsch an das Kommando übergeben. Dies ist nur möglich, wenn das Kommando selbst mit mehreren Parametern zurechtkommt und das +
unmittelbar den geschweiften Klammern folgt. Ein Beispiel mit du ergibt zunächst:
find . -name "*pdf" -exec du --total {} ";"
16 ./A.pdf 16 insgesamt 12 ./B.pdf 12 insgesamt 100 ./C.pdf 100 insgesamt
Dagegen erhält man ein sinnvolleres Ergebnis mit +
:
find . -name "*pdf" -exec du --total {} +
16 ./A.pdf 12 ./B.pdf 100 ./C.pdf 128 insgesamt
Mit -exec
& Co. kann man im Prinzip alles starten, was auch der Kernel starten könnte. Wenn man aber ein spezielles Sprachmittel einer Shell wie z.B. Befehlsverkettungen, Umleitungen, eingebaute Funktionen einsetzen möchte, wird das fehlschlagen. Man kann natürlich eine Shell wie die Bash per exec
starten und dieser eine mehrfach quotierte Zeichenkette zur Ausführung übergeben – mehrfach quotiert, weil dieser Einzeiler vor der Interpretation durch die aufrufende Shell und durch find und durch die von find gestartete Shell geschützt werden muss, was Schwindel, Schädelweh, mentale Depressionen und dergl. fast sicher erzeugen wird.
Besser sind diese Methoden:
Man erstellt ein Skript für die gewünschte Bearbeitung umd verwendet einen Aufruf wie:
find … -exec SKRIPT "{}" \;
oder wie:
find … -print | SKRIPT
Statt eines Skripts kann es natürlich auch ein anderes ausführbares Programm sein; manchmal ist dafür auch xargs hilfreich.
oder man baut find in das Skript ein:
# im Skript: find … -print | while read … do … done
Es gibt eine Unzahl weiterer Beispiele, z.B. die Suche nach Eigentümer, Berechtigungen, Dateisystem u.v.m. Siehe hierzu die Dokumentation.
Das oben unter Aufruf genannte Beispiel
find -P ~ -xdev -type f -printf '%s\t%k\t%p\n' | sort -g -r | head -n 5
funktioniert so:
Die (generelle) Option -P
kann man weglassen, da sie zum Standard gehört. Sie verhindert die Durchsuchung per symbolischer Links verknüpfter Ordner. Die globale Option -xdev
macht das ähnlich für die Einbindepunkte von anderen Dateisystemen. Beachte: Trotz vergleichbarer Semantik muss man die beiden Angaben syntaktisch unterschiedlich anwenden.
Die Tilde ~
wird von der aufrufenden Shell durch den Inhalt der Umgebungsvariable HOME
ersetzt.
Die Aktion -printf
erlaubt nicht nur die beliebige Formatierung der Funde, sondern beschafft über die mit dem Zeichen %
eingeleiteten Format-Spezifikationen auch Eigenschaften der Datei (was der Aufruf von printf
aus Programmiersprachen und das gleichnamige Programm nicht können); im Beispiel steht %s
für die Größe in Bytes, %k
für die belegte Größe in Kibibytes und %p
für Dateinamen mit Pfad, weitere siehe Dokumentation.
Weiteres Beispiel: Der Befehl
sudo find / -xdev \( -path /home -prune , ! -uid -1000 \) -printf '%U\t%g\t%p\n'
ermittelt alle Dateien außerhalb der persönlichen Benutzerverzeichnisse, die normalen Benutzern (mit UID ab 1000) gehören, davon sollte es nur sehr wenige mit plausiblen Erklärungen geben.
Funktionsweise:
Die Tests sollen hier nicht alle per Und verbunden werden, deshalb werden Klammern „( … )
“ verwendet. Klammern haben auch für die aufrufende Shell eine besondere Bedeutung, die hier nicht gemeint ist; deshalb werden hier die Klammern vor einer Interpretation durch die aufrufende Shell geschützt.
Im Klammerausdruck verbindet der Operator „,
“ zwei Ausdrücke:
Der linke (-path /home -and -prune
) sorgt dafür, dass dar Ordner /home nicht durchsucht wird. Das Arbeitsergebnis dieses Ausdrucks besteht nur aus dem Ordner /home selbst und wird verworfen.
Das Ergebnis des rechten Ausdrucks in der Klammer wird an die der schließenden Klammer folgenden Tests/Aktionen weiter gegeben und besteht aus allen Dateien, die „nicht Benutzern mit UIDs kleiner als 1000 gehören“.
Solche Konstrukte wie das hier beispielhaft gezeigte sind idiomatisch bei Verwendung der Aktion prune
.
Zu „Test“ (eigentlich globale Option) -xdev
und Aktion -printf
siehe vorstehendes Beispiel.
Beispielausgabe (gekürzt und teilweise zensiert):
1000 ░░░░░ /var/lib/samba/usershares/videos 1000 whoopsie /var/crash/_usr_bin_wireplumber.1000.crash 1000 ░░░░░ /var/log/installer/ubuntu_bootstrap.log.3376 1000 ░░░░░ /var/log/installer/ubuntu_bootstrap.log 1000 ░░░░░ /tmp/.X11-unix/X0
Dateien im Ordner /var/lib/samba/usershares/ entstehen durch persönliche Freigaben von Ordnern durch normale Benutzer im jeweiligen Homeverzeichnis. Samba erstellt an Hand dieser Dateien automatische Freigaben.
Dateien im Ordner /var/crash/ dokumentieren Systemabstürze und aus diesen automatisch generierte Fehlermeldungen an die Entwickler.
Im Ordner /tmp/ darf jeder Dateien ablegen und das System darf diese jederzeit löschen.
Unterordner von /var/mail/ können E-Mails des jeweiligen Benutzers enthalten.
Über alle anderen Fälle sollte der verantwortungsbewusste Systemverwalter nachdenken und, wenn keine plausible Erklärung gefunden werden kann, auch entschlossen seiner Verantwortung entsprechend handeln – denn in solchen Fällen stimmt etwas nicht mit dem System.
Wenn man find eine umfangreiche Aufgabe gibt, z.B. großer Suchbaum, komplizierte Tests, ungeschickte Formulierung von Aktionen mit zu vielen Subprozessen, dann kann das Programm sehr lange laufen, möglicherweise auch mehrere Stunden.
Der Eindruck, es würde niemals mehr zum Ende finden, ist jedoch nicht berechtigt. Selbst wenn man im Suchbaum mit symbolischen Links Schleifen erstellt hat, wird find diese erkennen und nur einmal durchlaufen.
Wer die Geduld verliert, kann die Suche mit der Taste Strg + C abbrechen.
Gelegentlich verweigert find mit einer Fehlermeldung die Ausführung. Die in der Praxis am häufigsten erscheinende Fehlermeldung erhält man durch fehlerhafte Verwendung von Mustern. Beispiel:
find $HOME -name .*
find: Pfade müssen dem Ausdruck `.bash_history' vorangestellt werden find: mögliches nicht zitiertes Muster nach Aussage '-name'?
Statt .bash_history kann auch ein beliebiger anderer Dateiname genannt werden, das ist halt der zufällig erste, den die aufrufende Shell bei der Auswertung des Globs gefunden hat. Das ist auch schon der Bedienfehler: Es wurde nicht verhindert, dass die aufrufende Shell den Glob auswertet. Korrekt ist:
find $HOME -name ".*"
(Die Formulierung „nicht zitiertes Muster“ ist eine schlechte Übersetzung von "unquoted pattern"; besser wäre hier „ungeschütztes Muster“.)
Warnungen sind tückischer als Fehlermeldungen, weil man die zuerst ausgegebenen Warnungen wegen der dann folgenden (vermutlich fehlerhaften) Ausgabe leicht übersehen kann und dann mit dem falschen Ergebnis weiterarbeitet.
In der Dokumentation wird beim Aufruf alles nach den Startpunkten als AUSDRUCK
benannt. Dieser kann globale Optionen (nicht zu verwechseln mit den generellen Optionen), positionelle Optionen, Tests, Operatoren und Aktionen beinhalten. Stehen globale Optionen, die immer für die ganze Suche gelten, nicht am Anfang des Ausdrucks, so sieht das aus, als habe der Nutzer eine andere Absicht gehabt, und man bekommt deshalb eine Warnung.
Beispiel: Der Befehl
find . -maxdepth 4 -name foo -or -maxdepth 2
ergibt eine Warnung
find: Warnung: Sie haben die globale Option -maxdepth nach dem Argument -name angegeben, aber globale Optionen sind nicht positionell, d.h. -maxdepth wirkt sich sowohl auf die davor als auch auf die danach angegebenen Tests aus. Bitte geben Sie globale Optionen vor anderen Argumenten an.
aus und anschließend eine Liste von Dateinamen, die aber vermutlich nicht der (mit find nicht realisierbaren) Vorstellung des Bedieners entspricht.
Im Beispiel war wohl die Absicht des Bedieners: „Suche bis zu 4 Stufen tief nach foo
und gebe das aus, oder, wenn es nicht gefunden wird, suche nut 2 Stufen tief und gebe das aus.“ Ein solche Anweisung kann find nicht erfüllen, denn wenn foo
nicht gefunden wird, hat es ja schon 4 Stufen durchsucht anstatt der dann verlangten 2.
Daraus ergibt sich die Regel für die Praxis:
Eine Angabe -maxdepth
ist nur einmal im Ausdruck
sinnvoll und man schreibt diese Angabe am besten als erstes in den Ausdruck. Das gilt entsprechend auch für -mindepth
.
findutils auf gnu.org 🇬🇧 – Sehr ausführliche Seite zum Thema Suche