Unix / Linux trova e ordina per data di modifica


138

Come posso fare un semplice findche ordinerebbe i risultati per l'ultima modifica?

Ecco l'attuale findche sto usando (sto facendo una fuga di shell in PHP, quindi questo è il ragionamento per le variabili):

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

Come potrei avere questo ordine con la ricerca modificata più di recente? (Nota: non voglio che ordini "dopo" la ricerca, ma piuttosto trovo i risultati in base a ciò che è stato modificato più di recente.)


github.com/shadkam/recentmost farebbe ciò che si desidera - ma bisogna costruirlo
user3392225

Risposte:


153

Usa questo:

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

printfargomenti di man find:

  • %Tk: Ora dell'ultima modifica del file nel formato specificato da k.

  • @: secondi dal 1 ° gennaio 1970, 00:00 GMT, con parte frazionaria.

  • c: data e ora della locale (sab 04 nov 12:02:33 EST 1989).

  • %p: Nome del file.


5
+1 Molto utile, la prima risposta a questa ho trovato con un risultato leggibile / utile
Jake N

più affidabile (e molto semplice) dato che il tempo è concesso per essere numericamente sequenziale (quindi sempre ordinabile), grazie!
Aquarius Power il

1
Ho questo alias per trovare i file recenti nel mio ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; }trova ricorsivamente tutti i file contenenti lo schema del primo argomento passato al comando ( fr <pattern>) e li ordina con l'ultimo più recente.
joelostblom,

Questo è fantastico !!! Per utilizzare con i find -L ...
collegamenti

1
Potresti voler usare ssedper sbarazzarti della parte frazionaria dei secondi e usare ISO8601 come ha mostrato @PeterMortensen:find . -type f -printf "%TY-%Tm-%TdT%TT %p\n" | sort -r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'
Ludovic Kuty

83

Il metodo più semplice è usare zsh, grazie ai suoi qualificatori glob .

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

Se hai GNU find, fallo stampare i tempi di modifica del file e ordina per quello.

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

Se hai GNU find ma non altre utility GNU, usa newline come separatori anziché null; perderai il supporto per i nomi di file contenenti newline.

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

Se hai Perl (qui suppongo che non ci siano nuove righe nei nomi dei file):

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

Se hai Python (anche assumendo che non ci siano nuove righe nei nomi dei file):

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'

Probabilmente c'è un modo per fare lo stesso in PHP, ma non lo so.

Se vuoi lavorare solo con strumenti POSIX, è piuttosto complicato; vedi Come elencare i file ordinati in modo ricorsivo per data di modifica (nessun comando stat disponibile!) (ritattare i primi 10 è la parte facile).


Penso che la findversione mostri i file più vecchi e che sia necessario aggiungere l' -ropzione sort.
Quentin Pradet,

Mia sed dice che non ha un'opzione -z.
Kef Schecter,

@KefSchecter Quindi usa le nuove righe come separatori, ma perderai il supporto per le nuove righe nei nomi dei file.
Gilles,

Quanto sopra è per python2. Se hai solo python3, alcune piccole modifiche: python3 -c 'import os, sys; times = {} per f in sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime per f in (ordinato (times.keys (), chiave = lambda f: times [f], reverse = True)) [: 10]: print (f); '
Neil McGill,

40

Non è necessario PHP o Python, solo 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 "{}" +;

Se il comando * termina con uno stato di errore (ovvero l' elenco degli argomenti troppo lungo ), è possibile scorrere con find. Parafrasato da: la lunghezza massima degli argomenti per un nuovo processo

  • find . -print0|xargs -0 command (ottimizza la velocità, se find non implementa "-exec +" ma conosce "-print0")
  • find . -print|xargs command (se non c'è spazio bianco negli argomenti)

Se la maggior parte degli argomenti è costituita da percorsi lunghi, assoluti o relativi, prova a spostare le tue azioni nella directory: cd /directory/with/long/path; command *E un'altra soluzione rapida potrebbe essere quella di abbinare meno argomenti:command [a-e]*; command [f-m]*; ...


1
Se ci sono molti file, ciò non riesce con 'Elenco argomenti troppo lungo' in ls.
occulus,

1
È vero, ma credo che la domanda fosse "come posso fare una semplice scoperta ..."
Ярослав Рахматуллин,

2
Non cita i nomi dei file in un modo che Xargs può capire (nessuna opzione -0, e i vari stili di citazione sono inadeguati)
Tobu

10

Hai solo bisogno di ls

Puoi fare find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;come sopra indicato,

o

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

2
Se ci sono molti file, ciò non riesce con 'Elenco argomenti troppo lungo' in ls. Forse ti ricordi di usare xargs?
occulus,

2
Ma se xargschiama lspiù volte, l'ordinamento verrà interrotto.
Aaron D. Marasco,

Questo non riesce per i file con spazi nei loro nomi. Qualche consiglio?
user74094

Mi sono appena imbattuto in questa risposta ed era esattamente ciò di cui avevo bisogno in una situazione simile. Domanda: cosa fa +;alla fine? Sembra dare lo stesso risultato senza il ;tuttavia non funziona senza il +?
RocketNuts,

Questa è esattamente la stessa di un'altra risposta postata 8 mesi prima, fatta eccezione per la parte sull'uso di "ls -1rt` find ... `", che è interrotta
Clément

7

Estensione della risposta dell'utente195696 :

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

Per ogni file, questo prima genera il timestamp numerico (per l'ordinamento per, seguito dalla tabulazione \t), quindi un timestamp leggibile dall'uomo, quindi la dimensione del file (purtroppo findnon è -printfpossibile fare in mebibyte, solo kibibyte), quindi il nome file con relativo sentiero.

Quindi lo sort -nordina in base al primo campo numerico.

Quindi cutsi libera di quel primo campo numerico che non è di alcun interesse per l'utente. (Stampa dal secondo campo in poi.) Il separatore di campo predefinito è \to tabulazione.

Esempio di output:

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

Ho creato deliberatamente il campo dimensione file 6 caratteri, perché se allungandolo diventa difficile distinguere visivamente quanto sono grandi i file. In questo modo, i file più grandi di 1e6 KiB escono: per 1 carattere significa 1-9 GB, per 2 caratteri significa 10-99 GB, ecc.


Modifica: ecco un'altra versione (poiché si find . -printf "%Tc"arresta in modo anomalo su MinGW / MSYS):

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

Dare output come:

-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

Dove:

  • -I{}fa sì che la ricorrenza {}sia sostituita da un argomento, e le nuove righe sono ora i separatori degli argomenti (notare gli spazi nei nomi dei file sopra).

  • ls -G sopprime la stampa del nome del gruppo (spreco di spazio).

  • ls -h --siproduce dimensioni di file leggibili dall'uomo (più corrette con --si).

  • ls -t ordina per tempo, il che è irrilevante qui, ma è quello che di solito uso.


1
Nota: per ordinare invece per dimensione del file , è sufficiente sostituire il T@da suno dei comandi sopra.
Evgeni Sergeev,

3

Variante OS X della risposta di @ user195696:

  1. Con data e ora:

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

    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

Ho scoperto che questo fa il lavoro su Mac OS X (e abbastanza generico per funzionare anche su altri Unixen):

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

2
Purtroppo, questo stampa i nomi dei mesi localizzati sulla mia configurazione croata, rendendo l'ordinamento errato.
Ivan Vučica,

La risposta di user195696 funziona per la configurazione croata (e altre).
Peter Mortensen,

1

Se la findselezione è molto semplice, potresti essere in grado di farne a meno e utilizzare solo ls:

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

1

Provare:

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

Ma è anche utile filtrare i dati per -mmin/ -mtimee -type.


1

Uso:

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

Questo comando ordina i file per data modificata.

E mostrati come:

[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

Ho migliorato questo script per gestire gli spazi bianchi nei nomi dei file, vedi superuser.com/a/777007/134532
Jan

1

Ho una soluzione semplice che funziona sia per FreeBSD (OS X) sia per Linux:

find . -type f -exec ls -t {} +

Funziona perfettamente - dovrebbe essere una risposta corretta, o almeno un punteggio più alto!
digitaltoast

0

Non credo che findabbia alcuna opzione per modificare l'ordinamento di output. -mtimee -mminti consentirà di limitare i risultati ai file che sono stati modificati entro un determinato intervallo di tempo, ma l'output non verrà ordinato: dovrai farlo da solo. GNU findha -printfun'opzione che, tra le altre cose, ti permetterà di stampare il tempo di modifica di ogni file trovato (stringhe di formato %to %Tk); ciò potrebbe aiutarti a ordinare l' findoutput nel modo desiderato.


0

Ho migliorato la risposta di Akashs rendendo lo script che gestisce correttamente gli spazi bianchi nei nomi dei file:

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

Se vuoi ordinare tutti i file PNG per tempo in $PWD:

Questo semplice one-liner offre tutta la flessibilità delle espressioni regolari su finde su ls.

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

0

È possibile utilizzare statsu BSD e Linux (non su POSIX) in questo modo:

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

Se vuoi limitare il numero:

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

0

Esiste un modo pulito e robusto sort | headper data:

Usando ls -lper la stampa carina

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

Come una funzione :

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

Questo potrebbe essere eseguito con uno o due argomenti, o anche senza:

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

Campione:

findByDate

Elencherà tutte le non directory ordinate per data. Nota:

Anche su un grande albero di filesystem, poiché xargs ricevi già un elenco ordinato, l'ordine dei file rimane corretto, anche se lsdeve essere eseguito più volte.

findByDate -h 12

Elencherà altre 12 directory non recenti ordinate per data, con le dimensioni stampate in forma leggibile dall'uomo

findByDate 42 '-type l'

Elencherà altri 42 link simbolici recenti

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

Elencherà tutti i collegamenti simbolici, i dispositivi a blocchi, i dispositivi socket e caratteri, ordinati per data.

Inversione dell'ordine

Sostituzione headdi taile cambiare interruttore di sorte 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}
}

Stessa funzione, stesso utilizzo:

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

-1

Se vuoi solo ottenere un percorso completo di ciascun elemento, puoi scrivere in questo modo.

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

Dove
-printf "% T @% p \ n" per fornire i criteri di ordinamento (data),
'sort -nr' per l'ordinamento per data,
capo -10 per elencare i primi 10 risultati,
tagliare -d '' -f 2 per tagliare il timestamp principale su ogni riga.


cut -d ' ' -f 2si interromperà se i nomi dei file contengono spazi.
F. Hauri,

-3

Ho una soluzione semplice.

Dopo cdin una directory, utilizzare

find . -iname "*" -ls


1
Questo non ordina per data di modifica.
David Post
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.