it-swarm.com.de

Unix/Linux findet und sortiert nach Änderungsdatum

Wie kann ich eine einfache find erstellen, die die Ergebnisse nach den zuletzt geänderten ordnet?

Hier ist die aktuelle find, die ich verwende (ich führe eine Shell-Escape-Operation in PHP durch, also ist dies 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.)

119
Richard Easton

Benutze das:

find . -printf "%[email protected] %Tc %p\n" | sort -n

printf Argumente aus man find :

  • %Tk: Der letzte Änderungszeitpunkt der Datei in dem durch k angegebenen Format.

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

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

  • %p: Dateiname.

127
user195696

Die einfachste Methode ist die Verwendung von zsh dank der glob-Qualifikationsmerkmale .

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 '%[email protected] %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

Wenn Sie GNU, aber keine anderen GNU Hilfsprogramme finden, verwenden Sie Zeilenumbrüche als Trennzeichen anstelle von Nullen. Sie verlieren die Unterstützung für Dateinamen mit Zeilenumbrüchen.

find -type f -printf '%[email protected] %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 Wie man Dateien rekursiv nach Änderungsdatum sortiert auflistet (kein stat-Befehl verfügbar!) (das erneute Verknüpfen der ersten 10 ist der einfache Teil).

82
Gilles

Sie brauchen weder PHP noch 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 beendet wird (dh Argumentliste zu lang ), können Sie mit find iterieren. Umschrieben aus: 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: cd /directory/with/long/path; command * Eine weitere schnelle Lösung könnte darin bestehen, weniger Argumente zu finden: command [a-e]*; command [f-m]*; ...

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`
9
skippy1910

Erweiterung der Antwort von user195696 :

find . -type f -printf "%[email protected]\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Für jede Datei wird zuerst der numerische Zeitstempel (zum Sortieren nach, gefolgt von der Tabellierung \t), dann ein lesbarer Zeitstempel, dann die Dateigröße (der -printf von find ist leider nicht in Mebibytes möglich, nur in Kibibytes) und dann der Dateiname mit ausgegeben relativer Pfad.

Dann sortiert sort -n es nach dem ersten numerischen Feld.

Dann entfernt cut das erste numerische Feld, das für den Benutzer nicht von Interesse ist. (Druckt das zweite Feld weiter.) Das Standardfeldtrennzeichen ist \t oder 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 (da find . -printf "%Tc" unter MinGW/MSYS abstürzt):

find . -type f -printf "%[email protected]\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

Woher:

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

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

  • ls -h --si erzeugt lesbare Dateigrößen (genauer mit --si).

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

6
Evgeni Sergeev

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) }'
    
3
user9399

Versuchen:

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

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

1
Good.Dima

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

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

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
1
Bryan Petty

Benutzen:

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
1
Akash

Ich glaube nicht, dass find Optionen zum Ändern der Ausgabereihenfolge hat. Mit -mtime und -mmin können Sie die Ergebnisse auf Dateien beschränken, die innerhalb eines bestimmten Zeitfensters geändert wurden. Die Ausgabe wird jedoch nicht sortiert - Sie müssen dies selbst tun. GNU find verfügt über eine -printf-Option, mit der Sie unter anderem die Änderungszeit jeder gefundenen Datei drucken können (Formatzeichenfolgen %t oder %Tk). Das kann Ihnen helfen, die Ausgabe von find nach Ihren Wünschen zu sortieren.

0
Jim Lewis

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
jan

Sie können stat unter BSD und Linux (nicht unter 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
drewk

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

Dieser einfache Einzeiler bietet die Flexibilität von regulären Ausdrücken für find und ls.

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