Unix / Linux findet und sortiert nach Änderungsdatum


138

Wie mache ich ein einfaches findVerfahren, bei dem die Ergebnisse nach den zuletzt geänderten geordnet werden?

Hier ist der Strom, den findich benutze (ich mache ein Shell-Escape in PHP, also ist das die Begründung für die Variablen):

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

Wie kann ich diese Reihenfolge ändern lassen, indem ich die Suche zuletzt ändere? (Hinweis: Ich möchte nicht, dass nach der Suche sortiert wird, sondern dass die Ergebnisse auf der Grundlage der zuletzt vorgenommenen Änderungen gefunden werden.)


github.com/shadkam/recentmost würde tun, was gewünscht wird - aber man muss es bauen
user3392225

Antworten:


153

Benutze das:

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

printfArgumente von man find:

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

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

  • cDatum und Uhrzeit des Gebietsschemas (Sa., 04. November, 12.02.33 EST, 1989).

  • %p: Dateiname.


5
+1 Sehr nützlich, die erste Antwort darauf habe ich mit einer lesbaren / nützlichen Datumsausgabe gefunden
Jake N

am zuverlässigsten (und sehr einfach), da die Zeit als numerisch sequentiell (also immer richtig sortierbar) eingestuft wird, thx!
Aquarius Power

1
Ich habe diesen Alias ​​für die Suche nach aktuellen Dateien in meinem ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; }Es werden rekursiv alle Dateien gesucht, die das Muster des ersten an command ( fr <pattern>) übergebenen Arguments enthalten, und diese werden mit dem letzten sortiert.
joelostblom

Das ist toll !!! Verwenden Sie zur Verwendung mit Symlinksfind -L ...
Varun Chandak

1
Sie können verwenden ssed, um den Sekundenbruchteil loszuwerden und ISO8601 zu verwenden, wie @PeterMortensen zeigte:find . -type f -printf "%TY-%Tm-%TdT%TT %p\n" | sort -r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'
Ludovic Kuty

83

Die einfachste Methode ist die Verwendung von zsh dank seiner Glob-Qualifier .

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

Wenn Sie GNU find haben, lassen Sie es die Datei-Änderungszeiten drucken und danach sortieren.

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\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 mit Zeilenumbrüchen.

find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10

Wenn Sie Perl haben (hier gehe ich davon aus, dass die Dateinamen keine Zeilenumbrüche enthalten):

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];
    }'

Wenn Sie Python haben (auch wenn Sie keine Zeilenumbrüche in den Dateinamen voraussetzen):

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'

Es gibt wahrscheinlich eine Möglichkeit, dasselbe in PHP zu tun, aber ich weiß es nicht.

Wenn Sie nur mit POSIX-Tools arbeiten möchten, ist dies etwas komplizierter. Siehe So listen Sie Dateien rekursiv nach Änderungsdatum sortiert auf (kein stat-Befehl verfügbar! ).


Ich denke, die findVersion zeigt die ältesten Dateien, und Sie müssen die -rOption hinzufügen sort.
Quentin Pradet

Mein Sed sagt, dass es keine -z Option gibt.
Kef Schecter

@KefSchecter Verwenden Sie dann Zeilenumbrüche als Trennzeichen, aber Sie verlieren die Unterstützung für Zeilenumbrüche in Dateinamen.
Gilles

Das obige ist für python2. Wenn Sie nur python3 haben, einige kleine Änderungen: python3 -c 'import os, sys; times = {} für f in sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime für f in (sortiert (times.keys (), key = lambda f: times [f], reverse = True)) [: 10]: print (f); '
Neil McGill

40

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 (dh einer zu langen Argumentliste ) beendet wird, können Sie mit find iterieren. Umschrieben von: Die maximale Länge der Argumente für einen neuen Prozess

  • find . -print0|xargs -0 command (optimiert die Geschwindigkeit, wenn find "-exec +" nicht implementiert, aber "-print0" kennt)
  • find . -print|xargs command (wenn die Argumente keine Leerzeichen enthalten)

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


1
Wenn viele Dateien vorhanden sind, schlägt dies fehl, und die Liste der Argumente ist im ls zu lang.
Occulus

1
Das ist wahr, aber ich glaube, die Frage war "Wie mache ich einen einfachen Fund ..."
Ярослав Рахматуллин

2
ls zitiert Dateinamen nicht in einer Weise, die xargs verstehen kann (keine Option -0, und die verschiedenen Anführungszeichenstile sind unzureichend)
Tobu

10

Sie brauchen nur ls

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

oder

ls -1rt `find /wherever/your/file/hides -type f`

2
Wenn viele Dateien vorhanden sind, schlägt dies fehl, und die Liste der Argumente ist im ls zu lang. Vielleicht recook um xargs zu benutzen?
Occulus

2
Aber wenn xargsAnrufe lsmehrmals, wird die Art gebrochen werden.
Aaron D. Marasco

Dies schlägt bei Dateien mit Leerzeichen im Namen fehl. Irgendein Rat?
user74094

Bin nur auf diese Antwort gestoßen und es war genau das, was ich in einer ähnlichen Situation brauchte. Frage: Was macht der +;am Ende? Es scheint dasselbe Ergebnis zu geben, ohne das ;es jedoch nicht funktioniert, ohne das +?
RocketNuts

Dies ist genau das Gleiche wie eine andere Antwort, die 8 Monate zuvor gepostet wurde, mit Ausnahme des Teils über die Verwendung von "ls -1rt` find… `", der kaputt ist
Clément

7

Die Ausweitung user195696 Antwort :

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

Für jede Datei wird diese erste gibt den numerischen Zeitstempel (zum Sortieren von durch Tabellierung gefolgt \t), dann eine für Menschen lesbare Zeitstempel, dann wird der Dateigröße (leider find‚s -printfin mebibytes nicht tun, nur kibibytes), dann wird der Dateiname mit relativer Pfad.

Dann sort -nsortiert sie nach dem ersten numerischen Feld.

Dann cutwird das erste numerische Feld entfernt, das für den Benutzer nicht von Interesse ist. (Druckt das zweite Feld weiter.) Das Standardfeldtrennzeichen ist \toder tabellarisch.

Ausgabebeispiel:

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 mit der Dateigröße absichtlich auf 6 Zeichen erweitert, da bei einer längeren Länge die visuelle Unterscheidung der Dateigröße schwierig wird. Auf diese Weise ragen Dateien über 1e6 KiB heraus: 1 Zeichen bedeutet 1-9 GB, 2 Zeichen bedeuten 10-99 GB usw.


Edit: hier ist eine andere Version (seit find . -printf "%Tc"Abstürzen auf MinGW / MSYS):

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

Ausgabe geben 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:

  • -I{}bewirkt, dass das Vorkommen von {}durch ein Argument ersetzt wird, und Zeilenumbrüche sind jetzt die Argumenttrennzeichen (beachten Sie die Leerzeichen in den Dateinamen oben).

  • ls -G Unterdrückt das Drucken des Gruppennamens (Platzverschwendung).

  • ls -h --siErzeugt lesbare Dateigrößen (korrekter mit --si).

  • ls -t sortiert nach Zeit, was hier irrelevant ist, aber das ist es, was ich normalerweise benutze.


1
Hinweis: von Datei zu sortieren Größe stattdessen einfach ersetzen die T@durch sin einem der oben genannten Befehle.
Evgeni Sergeev

3

OS X-Variante der Antwort von @ user195696:

  1. Mit Zeitstempel:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. Ohne Zeitstempel:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    

2

Ich stellte fest, dass dies unter Mac OS X erledigt wird (und generisch genug, um auch unter anderen Unixen zu funktionieren):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort

2
Leider druckt dies lokalisierte Monatsnamen in meinem kroatischen Setup aus, wodurch die Sortierung falsch wird.
Ivan Vučica

Die Antwort von user195696 funktioniert für das kroatische Setup (und andere).
Peter Mortensen

1

Wenn Ihre findAuswahl sehr einfach ist, können Sie möglicherweise darauf verzichten und einfach Folgendes verwenden ls:

ls -1 *.cc # -r -t optional

1

Versuchen:

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

Es ist aber auch nützlich, Daten nach -mmin/ -mtimeund zu filtern -type.


1

Verwenden:

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 wie folgt darstellen:

[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

Ich verbessern diese sript zu behandeln Leerzeichen in Dateinamen finden superuser.com/a/777007/134532
Januar

1

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 {} +

Das funktioniert einwandfrei - sollte richtig beantwortet werden, oder zumindest höher bewertet werden!
Digitaltoast

0

Ich glaube nicht, dass findes irgendwelche Optionen gibt, um die Ausgabereihenfolge zu ändern. -mtimeMit und -mminkönnen 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 findhat eine -printfOption, mit der Sie unter anderem die Änderungszeit jeder gefundenen Datei (Format Strings %toder %Tk) ausdrucken können . Das kann Ihnen helfen, die findAusgabe nach Ihren Wünschen zu sortieren .


0

Ich habe Akashs Antwort verbessert, indem ich das Skript so eingestellt habe, dass es Whitespace in Dateinamen korrekt verarbeitet:

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

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

Dieser einfache Einzeiler gibt die Flexibilität von regexp auf findund auf ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less

0

Sie können statBSD und Linux (nicht POSIX) folgendermaßen verwenden:

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

Wenn Sie die Anzahl begrenzen möchten:

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

0

Es gibt einen sauberen und robusten Weg, sort | headnach Datum zu suchen:

Verwenden Sie ls -lfür einen schönen Druck

find . ! -type d -printf "%T@ %p\0" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.]\+ //' |
    xargs -0 ls -lt

Als Funktion:

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

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

Usage: findByDate [-h] [lines] [find options]

Stichprobe:

findByDate

Listet alle Nicht-Verzeichnisse nach Datum sortiert auf. Kein:

Sogar auf großen Dateisystembaum, wie xargs bereits sortierte Liste erhalten, bleibt die Dateireihenfolge korrekt, auch wenn lsmuss oft ausgeführt werden.

findByDate -h 12

Listet 12 weitere Neuere auf, die keine Verzeichnisse sind, sortiert nach Datum, wobei die Größe in lesbarer Form gedruckt ist

findByDate 42 '-type l'

Wird 42 weitere symlinks auflisten

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

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

Reihenfolge umkehren

Ersetzen headdurch tailund wechseln von sortund ls:

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

Gleiche Funktion, gleiche Nutzung:

Usage: findByDate [-h] [lines] [find options]

-1

Wenn Sie nur einen vollständigen Pfad zu jedem Element erhalten möchten, können Sie dies wie folgt aufschreiben.

 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 der Sortierkriterien (Datum),
'sort -nr' für die Sortierung nach Datum,
head -10 für die Auflistung der Top-10-Ergebnisse,
cut -d '' -f 2 zum Ausschneiden des führender Zeitstempel in jeder Zeile.


cut -d ' ' -f 2wird unterbrochen, wenn Dateinamen Leerzeichen enthalten.
F. Hauri

-3

Ich habe eine einfache Lösung.

Nach cdeinem Verzeichnis verwenden

find . -iname "*" -ls


1
Dies wird nicht nach Änderungsdatum sortiert.
DavidPostill
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.