Schlagwort-Archive: find

Aktuellste/älteste Dateien in einem Verzeichniszweig ermitteln

Will man in einem einzelnen Verzeichnis die aktuellsten (oder ältesten) Dateien finden, geht das mit den Sortierungs-Optionen von ls:

ls -tr | tail

zeigt die neusten Dateien an (aktuellste am Ende). Umgekehrt für die ältesten:

ls -t | tail

Will (oder muss 😉 ) man aber eine ganze Verzeichnisstruktur durchsuchen, geht das mit ls nicht. Hier muss man find und stat zu Hilfe nehmen:

find . -exec stat --format '%y %n' {} ; | sort | tail

So erhält man die neusten Dateien, z.B.:

2010-11-08 10:55:49.000000000 +0100 ./javascript/selectm.js
2010-11-08 10:55:59.000000000 +0100 ./Formulareinm.php
2010-11-08 10:57:16.000000000 +0100 ./Eintragenm.php
2012-04-02 10:52:40.000000000 +0200 ./nop.html
2012-04-02 11:02:00.000000000 +0200 ./.htaccess
2012-07-10 17:06:16.000000000 +0200 ./phpinclude/autoabfrage.inc
2012-07-10 17:13:34.000000000 +0200 ./phpinclude/ergebnis.inc
2014-03-04 16:17:58.000000000 +0100 ./phpinclude
2018-10-23 10:22:02.000000000 +0200 ./phpinclude/send_infoMail.inc
2019-04-26 11:51:36.000000000 +0200 .

Will man die ältesten, so muss man die Reihenfolge mit den Sort-Parameter -r umkehren:

find . -exec stat --format '%y %n' {} ; | sort -r | tail

Dateien mit find suchen und verschieben

Will man Dateien, die sich per find finden lassen, in ein anderes Verzeichnis verschieben, gelingt das nur mit ein paar kleinen Tricks.

Beispielsweise sollen in einem Doku-Wiki-Verzeichnis alle zu foo.txt gehörenden Dateien in das Unterverzeichnis bar verschoben werden (wobei die entspr. bar-Verzeichnisse bereits existieren). Man denk natürlich zunächst an so was:

find . -name "foo*" -exec mv "{} `dirname {}`/bar/`basename {}`" ;

Leider funktioniert das so nicht, weil dirname {} nur . (einen Punkt) zurück liefert.

Nun kann man dirname ja durch ${VAR%/*} ersetzen, aber das funktioniert mit find nur in einer Sub-Shell:

find . -name "foo*" -ok sh -c 'mv -v $0 ${0%/*}/bar/${0##*/}' {} ;

Das funktioniert und dank -ok statt -exec fragt find vor jeder Befehlsausführung, ob das tatsächlich gemacht werden soll. Dabei fällt dann auf, dass find auch gerne die gerade eben verschobene Datei nochmal verschieben möchte. Um das zu verhindern, muss der Zielpfad ausgeklammert werden. Das gelingt so:

find . -name "foo*" -not -path '*/bar/*' -ok sh -c 'mv -v $0 ${0%/*}/bar/${0##*/}' {} ;

Dateien mit Sym- oder Hardlinks finden

Symlinks finden

Das Verlinken von Dateien oder Verzeichnissen per Symlink ist eine prima Sache. Schwierig wird es nur, wenn man Dateien löscht oder verschiebt, auf die Symlinks zeigen. Diese laufen dann nämlich ins Leere. Um zu prüfen, ob es Symlinks auf eine Datei oder ein Verzeichnis gibt, nutz man das folgende Kommando:

find / -type l -print | xargs ls -ld | grep 'dateiname'

Das kann ich auch verwenden, wenn ich z.B. ein Verzeichnis verschieben will und nicht weiß, ob es Links auf Dateien oder Unterverzeichnisse im fraglichen Verzeichnis gibt. Ich setze dann als ‚dateiname‘ den Namen des Verzeichnisses ein, das ich verschieben will.

Siehe auch http://www.grymoire.com/Unix/Find.html#uh-6

Hardlinks finden

Mitunter benutzt man auch Hardlinks, um Dateien zu verlinken (z.B. Backup mit rsync, wie in der c’t 07/2009, S. 212 beschrieben). Hat man nun eine Datei, bei der man anhand des Linkcount erkennt, dass sie Hardlinks hat, will man evt. auch wissen, wo die anderen Links liegen. Mit

find . ! -type d -links +1 -ls|sort -n

findet man alle Dateien, deren Linkcount größer 1 ist. Durch die Sortierung anhand des Inodes (erste Spalte) kann man gut zusammengehörende Dateien erkennen.

Will man für eine Bestimmte Datei die zugehörigen Links finden, geht das auch so:

f=`ls -i dateiname |awk '{print $1}'`
find / -inum $f

Siehe auch: The UNIX and Linux Forums: search for hardlinks based on filename via find command.

Dateien an Hand des Datums und der Uhrzeit finden

Manchmal muss man eine Datei finden, von der man nur weiß, wann sie zuletzt geändert wurde. Weiß man, dass das vor 3 Tagen war, hilft einem die Option -mtime +3 des Befehls find. Hat man aber ein Datum und eine Uhrzeit, muss man ein wenig tricksen.

Man kann hier die Option -newer zusammen mit einer Referenzdatei verwenden. Diese Referenzdatei kann mit touch erstellt werden. Da wir einen bestimmten Zeitpunkt suchen, brauchen wir noch eine zweite Referenzdatei, da -newer sonst alle neueren Dateien ausgibt.

$ touch -t 11142104 /tmp/tmp_start
$ touch -t 11142105 /tmp/tmp_end
$ find /opt -newer /tmp/tmp_start ! -newer /tmp/tmp_end

Dies findet Dateien im Verzeichnis /opt und darunter, die zuletzt am 14.November um 21:04 Uhr modifiziert wurden.

Dieses Beispiel funktioniert unter Linux, aber auch unter HP-UX, dessen Befehle find und touch leider nicht so viele Optionen kennen wie die Linux-Versionen

Dateien finden, die nicht von allen gelesen werden können

Manchmal muss man die Dateien finden, deren Rechte so gesetzt sind, dass sie nicht von allen gelesen werden können. Mit

find . -type f -not -perm -0004 -ls

findet man alle Dateien im aktuellen Verzeichnis und darunter, deren Worldreadable-Bit nicht gesetzt ist.

Und so macht man sie für alle lesbar:

find . -type f -not -perm -0004 -exec chmod -c a+r {} ;

Das gleiche für Verzeichnisse:

find . -type d -not -perm -0004 -exec chmod -c a+rx {} ;