2011-06-07 18:23:57 +0000 2011-06-07 18:23:57 +0000
152
152

Unix/Linux suchen und sortieren nach Änderungsdatum

Wie kann ich ein einfaches find machen, das die Ergebnisse nach der letzten Änderung ordnet?

Hier ist das aktuelle find, das ich verwende (ich mache einen Shell-Escape in PHP, daher die Variablen):

find '$dir' -name '$str'\* -print | head -10

Wie kann ich die Suche nach der letzten Änderung ordnen? (Beachten Sie, dass ich nicht möchte, dass es “nach” der Suche sortiert, sondern die Ergebnisse basierend auf der letzten Änderung findet).

Antworten (17)

168
168
168
2013-02-05 13:31:01 +0000

Verwenden Sie dies:

find . -printf "%T@ %Tc %p\n" | sort -n

printf Argumente aus man find :

  • %Tk: Letzte Änderungszeit der Datei in dem von k angegebenen Format.

  • @: Sekunden seit dem 1. Januar 1970, 00:00 GMT, mit Nachkommastelle.

  • c: Datum und Uhrzeit des Gebietsschemas (Sat Nov 04 12:02:33 EST 1989).

  • %p: Name der Datei.

85
85
85
2011-06-07 18:39:34 +0000

Die einfachste Methode ist, zsh zu verwenden, dank seiner glob qualifiers .

print -lr -- $dir/**/$str*(om[1,10])

Wenn Sie GNU find haben, lassen Sie es die Änderungszeiten der Dateien ausgeben und sortieren Sie danach.

find -type f -printf '%T@ %p```
find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^]* //' | head -n 10
```' |
sort -zk 1nr |
sed -z 's/^[^]* //' | tr '```
find . -type f -print |
perl -l -ne '
    $_{$_} = -M; # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_; # sort by increasing age
        print @sorted[0..9];
    }'
```' '\n' | head -n 10

Wenn Sie GNU find, aber keine anderen GNU-Dienstprogramme haben, verwenden Sie Zeilenumbrüche als Trennzeichen anstelle von Nullen; Sie verlieren die Unterstützung für Dateinamen, die Zeilenumbrüche enthalten.

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f], reverse=True))[:10]: print f'

Wenn Sie Perl haben (hier nehme ich an, dass es keine Zeilenumbrüche in Dateinamen gibt):

0x1&

Wenn Sie Python haben (auch unter der Annahme, dass es keine Zeilenumbrüche in Dateinamen gibt):

0x1&

Es gibt wahrscheinlich eine Möglichkeit, dasselbe in PHP zu tun, aber ich kenne sie nicht.

Wenn Sie nur mit POSIX-Tools arbeiten wollen, ist es etwas komplizierter; siehe Wie man Dateien rekursiv nach Änderungsdatum sortiert auflistet (kein stat-Befehl verfügbar!) (das Wiederholen der ersten 10 ist der einfache Teil).

41
41
41
2011-06-16 18:11:00 +0000

Sie brauchen kein PHP oder Python, nur ls :

man ls:
-t sort by modification time
-r, reverse order while sorting (--reverse )
-1 list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Wenn der Befehl * mit einem Fehlerstatus (d. h. Argumentenliste zu lang ) beendet wird, können Sie mit find iterieren. Paraphrasiert von: Die maximale Länge der Argumente für einen neuen Prozess

  • find . -print0|xargs -0 command (optimiert die Geschwindigkeit, wenn find nicht “-exec +” implementiert, sondern “-print0” kennt)
  • find . -print|xargs command (wenn es keine Leerzeichen in den Argumenten gibt)

Wenn der größte Teil der Argumente aus langen, absoluten oder relativen Pfaden besteht, dann versuchen Sie, Ihre Aktionen in das Verzeichnis zu verschieben: cd /directory/with/long/path; command * Und eine andere schnelle Lösung kann darin bestehen, weniger Argumente anzupassen: command [a-e]*; command [f-m]*; ...

10
10
10
2012-05-18 07:58:06 +0000

Sie benötigen nur ls

Sie könnten find /wherever/your/files/hide -type f -exec ls -1rt "{}" +; wie oben angegeben,

oder

ls -1rt `find /wherever/your/file/hides -type f`
``` verwenden
8
8
8
2014-04-24 08:12:01 +0000

Erweiterung der Antwort von user195696 :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Für jede Datei wird zuerst der numerische Zeitstempel ausgegeben (für die Sortierung nach, gefolgt von der Tabellierung \t), dann ein menschenlesbarer Zeitstempel, dann die Dateigröße (leider kann find nicht in mebibytes, nur kibibytes), dann der Dateiname mit relativem Pfad.

Dann -printf sortiert es nach dem ersten numerischen Feld.

Dann sort -n entsorgt das erste numerische Feld, das den Benutzer nicht interessiert. (Ab dem zweiten Feld wird gedruckt.) Der Standard-Feldtrenner ist cut oder Tabulierung.

Beispiel für die Ausgabe:

Thu 06 Feb 2014 04:49:14 PM EST 64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST 0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST 64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST 0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST 64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST 9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST 9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST 9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST 32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST 0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST 70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST 70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST 70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST 0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST 32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST 32 KiB ./plot_grid.m

Ich habe das Feld für die Dateigröße absichtlich 6 Zeichen lang gemacht, denn wenn man es länger macht, wird es schwer, visuell zu unterscheiden, wie groß die Dateien sind. Auf diese Weise ragen Dateien, die größer als 1e6 KiB sind, heraus: bei 1 Zeichen bedeutet das 1-9 GB, bei 2 Zeichen 10-99 GB, usw.


Bearbeiten: hier ist eine andere Version (da \t auf MinGW/MSYS abstürzt):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Ergibt Ausgaben wie:

-rw-r--r-- 1 es 23K Jul 10 2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Wo:

  • find . -printf "%Tc" bewirkt, dass das Auftreten von -I{} durch ein Argument ersetzt wird, und Zeilenumbrüche sind jetzt die Argumenttrenner (beachten Sie die Leerzeichen in den Dateinamen oben).

  • {} unterdrückt die Ausgabe des Gruppennamens (Platzverschwendung).

  • ls -G erzeugt menschenlesbare Dateigrößen (korrekter mit ls -h --si).

  • --si sortiert nach Zeit, was hier irrelevant ist, aber das ist es, was ich typischerweise verwende.

4
4
4
2016-02-24 15:18:34 +0000

OS X-Variante der Antwort von @user195696:

  1. mit Zeitstempel:

  2. Ohne Zeitstempel:

2
2
2
2019-03-12 19:32:27 +0000

Ich habe eine einfache Lösung, die sowohl für FreeBSD (OS X) als auch für Linux funktioniert:

find . -type f -exec ls -t {} +
2
2
2
2012-07-26 07:42:44 +0000

Ich habe herausgefunden, dass dies unter Mac OS X (und generisch genug, um auch unter anderen Unixen zu funktionieren) die Aufgabe erfüllt:

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
1
1
1
2013-12-08 09:14:14 +0000

Verwenden Sie:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

Dieser Befehl sortiert Dateien nach Änderungsdatum.

Und zeigt an wie:

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
1
1
1
2014-05-02 11:16:59 +0000

Wenn Ihre find-Auswahl sehr einfach ist, können Sie vielleicht darauf verzichten und nur ls verwenden:

ls -1 *.cc # -r -t optional
0
0
0
2014-07-04 14:58:50 +0000

Ich habe Akashs Antwort verbessert, indem ich dafür gesorgt habe, dass das Skript Whitespace in Dateinamen korrekt behandelt:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';
0
0
0
2019-09-11 08:23:43 +0000

Es gibt einen sauberen und robusten Weg für sort | head nach Datum:

Verwendung von ls -l für pretty print

find . ! -type d -printf "%T@ %p```
findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zrn |
        head -zn ${1:--0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dlt${humansize}
}
```" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.] //' |
    xargs -0 ls -lt

Als eine bash Funktion:

findByDate

Dies könnte mit einem oder zwei Argumenten ausgeführt werden, oder auch ohne:

findByDate -h 12

Beispiel:

findByDate 42 '-type l'

Wird alle Nicht-Verzeichnisse sortiert nach Datum auflisten. Hinweis:

Auch bei einem großen Dateisystembaum bleibt die Reihenfolge der Dateien korrekt, auch wenn xargs mehrmals ausgeführt werden muss, da ls eine bereits sortierte Liste erhält.

findByDate -0 '( -type l -o -type b -o -type s -o -type c )'

Listet 12 weitere neuere Nicht-Verzeichnisse auf, sortiert nach Datum, mit Größe in menschlich lesbarer Form

findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zn |
        tail -zn ${1:-+0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dltr${humansize}
}

Listet 42 weitere neuere Symlinks

0x1&

Listet alle Symlinks, Blockgeräte, Sockets und Zeichengeräte auf, sortiert nach Datum.

Umkehrung der Reihenfolge

Ersetzen von head durch tail und Umschalten von sort und ls:

0x1&

Gleiche Funktion, gleiche Verwendung:

0x1&

0
0
0
2011-06-07 18:33:10 +0000

Ich glaube nicht, dass find irgendwelche Optionen hat, um die Reihenfolge der Ausgabe zu ändern. -mtime und -mmin lassen Sie die Ergebnisse auf Dateien beschränken, die innerhalb eines bestimmten Zeitfensters geändert wurden, aber die Ausgabe wird nicht sortiert – das müssen Sie selbst tun. GNU find hat eine Option -printf, mit der Sie unter anderem die Änderungszeit jeder gefundenen Datei ausgeben können (Format-Strings %t oder %Tk); das könnte Ihnen helfen, die find-Ausgabe so zu sortieren, wie Sie es wünschen.

0
0
0
2018-06-24 23:33:20 +0000

Sie können stat unter BSD und Linux (nicht unter POSIX) auf diese Weise verwenden:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

Wenn Sie die Anzahl begrenzen wollen:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-
0
0
0
2014-05-17 10:55:57 +0000

Wenn Sie alle PNG-Dateien nach Zeit in $PWD ordnen möchten:

Dieser einfache Einzeiler bietet die ganze Flexibilität von regexp auf find und auf ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
-1
-1
-1
2017-03-28 01:13:40 +0000

Wenn Sie nur einen vollständigen Pfad für jedes Element erhalten möchten, können Sie so schreiben.

find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

Wobei -printf “%T@ %p\n ” für die Angabe von Sortierkriterien (Datum), ‘sort -nr’ für die Sortierung nach Datum, head -10 für die Auflistung der Top-10-Ergebnisse, cut -d ‘ ’ -f 2 für das Abschneiden des führenden Zeitstempels in jeder Zeile.

-3
-3
-3
2017-03-25 09:09:59 +0000

Ich habe eine einfache Lösung.

Nach cd in ein Verzeichnis, verwenden Sie

find . -iname "*" -ls