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

Unix/Linux zoeken en sorteren op datum gewijzigd

Advertisement

Hoe kan ik een eenvoudige find doen die de resultaten zou rangschikken volgens meest recent gewijzigd?

Hier is de huidige find die ik gebruik (ik doe een shell escape in PHP, dus dat is de redenering voor de variabelen):

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

Hoe kan ik dit de zoekopdracht laten ordenen op meest recent gewijzigd? (Merk op dat ik niet wil dat het sorteert ‘na’ het zoeken, maar eerder de resultaten wil vinden op basis van wat het meest recent is gewijzigd).

Advertisement
Advertisement

Antwoorden (17)

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

Gebruik dit:

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

printf argumenten van man find :

  • %Tk: Laatste wijzigingstijd van het bestand in het formaat gespecificeerd door k.

  • @: seconden sinds 1 jan. 1970, 00:00 GMT, met fractioneel deel.

  • c: locale’s datum en tijd (Sat Nov 04 12:02:33 EST 1989).

  • %p: Naam van het bestand.

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

De gemakkelijkste methode is om zsh te gebruiken, dankzij zijn glob qualifiers .

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

Als je GNU find hebt, laat het dan de wijzigingstijden van bestanden afdrukken en sorteer daarop.

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

Als je GNU find hebt maar geen andere GNU programma’s, gebruik dan newlines als scheidingsteken in plaats van nulls; je verliest dan ondersteuning voor bestandsnamen die newlines bevatten.

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'

Als je Perl hebt (hier ga ik ervan uit dat er geen newlines in bestandsnamen staan):

0x1&

Als je Python hebt (ook ervan uitgaande dat er geen newlines in bestandsnamen staan):

0x1&

Er is waarschijnlijk een manier om hetzelfde te doen in PHP, maar die ken ik niet.

Als je alleen met POSIX tools wilt werken, is het wat ingewikkelder; zie Hoe maak ik een lijst van bestanden gesorteerd op wijzigingsdatum recursief (geen stat commando beschikbaar!) (de eerste 10 opnieuw sorteren is het makkelijke deel).

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

U hoeft geen PHP of Python te gebruiken, alleen 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 "{}" +;

Als commando * eindigt met een foutstatus (d.w.z. Argumentenlijst te lang ), dan kun je itereren met find. Geparafraseerd van: De maximum lengte van argumenten voor een nieuw proces

  • find . -print0|xargs -0 command (optimaliseert de snelheid, als find “-exec +” niet implementeert maar wel “-print0” kent)
  • find . -print|xargs command (als er geen witruimte in de argumenten staat)

Als het grootste deel van de argumenten bestaat uit lange, absolute of relatieve paden, probeer dan je acties in de directory te verplaatsen: cd /directory/with/long/path; command * En een andere snelle oplossing kan zijn om minder argumenten te matchen: command [a-e]*; command [f-m]*; ...

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

Je hebt alleen ls

nodig Je zou kunnen doen find /wherever/your/files/hide -type f -exec ls -1rt "{}" +; zoals hierboven vermeld,

of

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

Uitbreiding van user195696’s antwoord :

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

Voor elk bestand voert dit eerst de numerieke tijdstempel uit (om op te sorteren, gevolgd door tabellering \t), dan een menselijk leesbare tijdstempel, dan de bestandsgrootte (helaas kan find niet in mebibytes doen, alleen kibibytes), dan de bestandsnaam met relatief pad.

Dan sorteert -printf het op het eerste numerieke veld.

Dan verwijdert sort -n dat eerste numerieke veld dat de gebruiker niet interesseert. (Drukt het tweede veld verder af.) Het standaard veldscheidingsteken is cut of tabellering.

Voorbeeld van uitvoer:

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

Ik heb het veld bestandsgrootte met opzet 6 karakters gegeven, want als je het langer maakt, wordt het moeilijk om visueel te onderscheiden hoe groot de bestanden zijn. Op deze manier springen bestanden groter dan 1e6 KiB eruit: met 1 karakter betekent 1-9 GB, met 2 karakters betekent 10-99 GB, enz.

  • *

Bewerk: hier is een andere versie (aangezien \t crasht op MinGW/MSYS):

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

Geeft uitvoer als:

-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

Waar:

  • find . -printf "%Tc" zorgt ervoor dat het voorkomen van -I{} wordt vervangen door een argument, en newlines zijn nu de argumentscheidingstekens (let op de spaties in bestandsnamen hierboven).

  • {} onderdrukt het afdrukken van de groepsnaam (verspilling van ruimte).

  • ls -G produceert menselijk leesbare bestandsgroottes (correcter met ls -h --si).

  • --si sorteert op tijd, wat hier niet relevant is, maar dat is wat ik meestal gebruik.

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

OS X variant van @user195696’s antwoord:

  1. Met tijdstempel:

  2. Zonder tijdstempel:

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

Ik heb een eenvoudige oplossing die werkt voor zowel FreeBSD (OS X) als Linux:

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

Ik heb ontdekt dat dit de klus klaart op Mac OS X (en generiek genoeg om ook op andere Unixen te werken):

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

Gebruik:

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

Dit commando sorteert bestanden op gewijzigde datum.

En wordt weergegeven als:

[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

Als je find selectie heel eenvoudig is, kun je het misschien zonder doen, en gewoon ls gebruiken:

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

Ik heb Akashs antwoord verbeterd door ervoor te zorgen dat het script correct omgaat met spaties in bestandsnamen:

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

Er is een schone en robuuste manier om sort | head op datum te zetten:

ls -l gebruiken voor mooie afdrukken

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 een bash functie:

findByDate

Dit kan worden uitgevoerd met één of twee argumenten, of zelfs zonder:

findByDate -h 12

Voorbeeld:

findByDate 42 '-type l'

Toont alle non directories gesorteerd op datum. Opmerking:

Zelfs op een groot bestandssysteem, omdat xargs al een gesorteerde lijst ontvangt, blijft de volgorde van de bestanden correct, zelfs als ls vele malen moet worden uitgevoerd.

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

Toont nog eens 12 recente niet-directories gesorteerd op datum, met grootte afgedrukt in menselijk leesbare vorm

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

Toont nog eens 42 recente symlinks

0x1&

Toont alle symlinks, block devices, sockets en characters devices, gesorteerd op datum.

Omkering van volgorde

Vervanging van head door tail en wissel van sort en ls:

0x1&

Dezelfde functie, hetzelfde gebruik:

0x1&

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

Ik denk niet dat find opties heeft om de volgorde van de uitvoer aan te passen. Met -mtime en -mmin kunt u de resultaten beperken tot bestanden die binnen een bepaald tijdsvenster zijn gewijzigd, maar de uitvoer wordt niet gesorteerd – dat zult u zelf moeten doen. GNU find heeft een -printf optie die, onder andere, toelaat om de wijzigingstijd van elk gevonden bestand af te drukken (formaat strings %t of %Tk) ; dat zou u kunnen helpen om de find uitvoer te sorteren zoals u wenst.

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

Je kunt stat op BSD en Linux (niet op POSIX) op deze manier gebruiken:

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

Als je het aantal wilt beperken:

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

Als je alle PNG bestanden wilt rangschikken op tijd in $PWD:

Deze eenvoudige one-liner geeft alle flexibiliteit van regexp op find en op ls.

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

Als je alleen een volledig pad van elk item wilt krijgen, kun je het als volgt opschrijven

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

Waarbij -printf “%T@ %p\n ” voor het geven van sorteercriteria (datum), ‘sort -nr’ voor sorteren op datum, head -10 voor het weergeven van de top 10 resultaten, cut -d ‘ ’ -f 2 voor het knippen van het voorlopende tijdstempel op elke regel.

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

Ik heb een eenvoudige oplossing.

Na cd naar een directory, gebruik dan

find . -iname "*" -ls

Advertisement

Gerelateerde vragen

6
10
5
37
5
Advertisement