Reduzieren Sie die Ausgabe einer rekursiven Verzeichnisliste

7

Gibt es eine Möglichkeit , um die Liste aus allen Dateien innerhalb eines Verzeichnisses Baum in einer einzigen Liste, nach Änderungszeit auf Linux sortiert?

ls -Rlt 

listet Dateien rekursiv auf, sie sind jedoch in der Ausgabe in verschiedenen Ordnern gruppiert, sodass die Ausgabe nicht als Ganzes sortiert ist. Nur der Inhalt jedes Verzeichnisses wird nach Zeit sortiert.

mahela007
quelle
Möchten Sie auch Verzeichnisse oder nur Dateien auflisten?
Terdon

Antworten:

11

Ja, das können Sie mit GNU machen find. Wenn Ihre Dateinamen keine Zeilenumbrüche enthalten, können Sie Folgendes tun:

find -printf '%T@ %p\n' | sort -gk1,1

Erläuterung

  • Mit der -printfOption findkönnen alle Arten von Informationen gedruckt werden. In diesem Fall verwenden wir:

    %Tk    File's last modification time in the format specified  by
           k, which is the same as for %A.
    @      seconds  since Jan. 1, 1970, 00:00 GMT, with fractional part.
    %p     File's name.
    

    So %T@ %p\ndruckt die Zeitpunkt der letzten Änderung der Datei in Sekunden seit der Epoche ( %T@), ein Leerzeichen und dann den Dateinamen ( %p).

  • Diese werden dann übergeben, an sortdie -nnur im ersten Feld ( -k1,1) numerisch ( ) sortiert werden soll .

Beachten Sie, dass dadurch alle Dateien und Verzeichnisse zurückgegeben werden. Um es nur auf reguläre Dateien zu beschränken (keine Verzeichnisse, Gerätedateien, Links usw.), fügen Sie -type fes Ihrem findBefehl hinzu.

Um lesbare Daten zu erhalten, können Sie die Ausgabe mit GNU verarbeiten date:

find -printf '%T@ %p\t\n' | sort -gk1,1 | 
    perl -lne 's/([^ ]*)//;chomp($i=`date -d \@$1`); print "$i $_"'

Hier perlersetzt der Befehl die erste Zeichenfolge von Nicht-Leerzeichen (das Datum) durch sich selbst, wie von GNU verarbeitet date.


Das Obige schlägt für Dateinamen fehl, die Zeilenumbrüche enthalten. Verwenden Sie zum Umgang mit Zeilenumbrüchen:

find -printf '%p\t%T@\0' | sort -zt$'\t' -nk2 | tr '\0' '\n'

Das ist das gleiche, außer dass findein \0statt eines \nam Ende jedes Dateinamens ausgegeben wird . GNU sortkann mit nulltrennenden Ausgaben umgehen, sodass es weiterhin korrekt sortieren kann. Der letzte trBefehl übersetzt das \0Zurück in \n.

terdon
quelle
Das mache ich auch (mit der Zeit zuerst). Es braucht auch GNU findutils.
Chexum
@chexum ah ja, danke. Ich vergesse immer wieder, dass -printfdas nicht POSIX ist.
Terdon
Danke für die Erklärung. Kann ich diesen Befehl ändern, um die Änderungszeiten in einem für Menschen lesbaren Format zu drucken?
Mahela007
@ Mahela007 ja. Sie müssten es verwenden, dateum es neu zu formatieren : find -printf '%T@ %p\t\n' | sort -gk1,1 | sed -E "s/([^ ]*)/$(date -d \1)/". Siehe aktualisierte Antwort. Ich habe auch die (völlig unnötige) Verwendung von Tabs behoben.
Terdon
@mikeserv in der Tat war ich nicht, danke. Es sollte jetzt funktionieren.
Terdon
5

Mit zsh:

print -rl -- **/*(D.om)

** / * stimmen mit jeder Ebene von Unterverzeichnissen überein (und folgen keinen Symlinks). D.Qualifizierer listen reguläre Dateien auf, omsortieren sie nach Änderungszeit, neueste zuerst.

Wenn Sie möchten, dass die Dateinamen ohne den Verzeichnisteil aufgelistet werden, fügen Sie den tVerlaufsmodifikator hinzu:

print -rl -- **/*(D.om:t)
cuonglm
quelle
was ist zsh ()
Mahela007
@ Mahela007: Es ist eine weitere Unix-Shell, mit vielen erweiterten Funktionen hinzugefügt zsh.org
cuonglm
0

ARG_MAXNun , wenn Sie über viele, viele tausend Dateien sprechen - und damit über Ihr Limit hinaus -, wird es nicht so gut herauskommen, aber die einfachste Lösung ist:

find . ! -type d -exec ls -t {} +

... die lsjeden Stapel von <=ARG_MAXDateien aufruft , den es finden kann. Es gibt auch keine willkürlichen Einschränkungen für die Zeichen in den Pfadnamen, nur für die maximale Anzahl von Argumenten, die zusammen verarbeitet werden können.

Die Ausgabe wird identisch mit findder Ausgabe geschrieben. Sie können natürlich auch jede andere Option verwenden, z. B. -loder GNUs -h. Hier sind einige davon, die von einem kleinen Baum aufgelistet wurden, den ich vor einer Woche erstellt habe:

find . ! -type d -exec ls -lht {} +

-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 19:00 ./dir/dir1/file
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 19:00 ./dir/dir2/file
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 19:00 ./dir/dir3/file
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 19:00 ./dir2/dir1/file
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 19:00 ./dir2/dir2/file
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 19:00 ./dir2/dir3/file
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 18:57 ./dir/file1
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 18:57 ./dir/file2
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 18:57 ./dir/file3
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 18:57 ./dir2/file1
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 18:57 ./dir2/file2
-rw-r--r-- 1 mikeserv mikeserv   0 Dec 19 18:57 ./dir2/file3

... die ganz offensichtlich nicht nach Verzeichnis gruppiert sind.

Auf meiner Maschine ...

getconf ARG_MAX

2091752

... aber ich denke nicht, dass das realistisch ist. Ich denke, es ist im Durchschnitt eher 65k oder so.

mikeserv
quelle