Come posso trovare il file più vecchio in una struttura di directory

Sto cercando una shell one-liner per trovare il file più vecchio in una struttura di directory.

  • Linux Mint VM in VirtualBox si blocca con l'errore DISKFULL
  • password ssh
  • È ansible mettere in background lo background senza sospensione (controllo + z)?
  • Qual è lo scopo principale del process di swapper in Unix?
  • Directory zip Unix, ma ha escluso specifiche sottodirectory (e tutto ciò che è all'interno di essi)
  • Come posso trovare file più grandi / piccoli di x byte?
  • Come cerca Unix per i file eseguibili?
  • Come chiudere tutti i processi di background in unix?
  • 8 Solutions collect form web for “Come posso trovare il file più vecchio in una struttura di directory”

    Questo lavoro (aggiornato per includere il suggerimento di Daniel Andersson):

    find -type f -printf '%T+ %p\n' | sort | head -n 1 

    Questo è un po 'più porttile e perché non si basa sulla GNU find extension -printf , quindi funziona anche su BSD / OS X:

     find . -type f -print0 | xargs -0 ls -ltr | head -n 1 

    L'unico inconveniente qui è che è un po 'limitato alla dimensione di ARG_MAX (che dovrebbe essere irrilevante per la maggior parte dei kernel più recenti). Quindi, se ci sono più di getconf ARG_MAX caratteri restituiti (262.144 sul mio sistema), non ti dà il risultato corretto. Non è anche conforms a POSIX perché -print0 e xargs -0 non lo sono.

    Alcune altre soluzioni a questo problema sono descritte qui: Come posso trovare il file più recente (più recente, il più antico, il più vecchio) in una directory? – Greg's Wiki

    I seguenti comandi comandi sono garantiti per funzionare con qualsiasi tipo di nomi di file strani:

     find -type f -printf "%T+ %p\0" | sort -z | grep -zom 1 ".*" | cat find -type f -printf "%T@ %T+ %p\0" | \ sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //' stat -c "%y %n" "$(find -type f -printf "%T@ %p\0" | \ sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //')" 

    L'utilizzo di un byte null ( \0 ) invece di un carattere di row di avanzamento ( \n ) assicura che l'output della ricerca sia ancora comprensibile nel caso in cui uno dei nomi di file contenga un carattere di row di avanzamento.

    L'interruttore -z rende entrambi gli ordinamenti e grep interpretano solo byte nullo come caratteri di fine linea. Poiché non esiste un tale interruttore per la testa, usiamo grep -m 1 invece (solo una occorrenza).

    I comandi sono ordinati per tempi di esecuzione (misurati sulla mia macchina).

    • Il primo command sarà il più lento dato che deve convertire il mtime di each file in un formato leggibile umano e poi ordinare quelle stringhe. La tubazione al gatto evita di colorare l'output.

    • Il secondo command è leggermente più veloce. Mentre esegue ancora la conversione della data, ordinare numberscamente ( sort -n ) i secondi trascorsi dall'epoca di Unix è un po 'più veloce. sed elimina i secondi dall'epoca di Unix.

    • L'ultimo command non ha alcuna conversione affatto e dovrebbe essere significativamente più veloce dei primi due. Il command find non visualizzerà il file mtime del file più vecchio, quindi è necessario stat.

    Pagine man correlate: find – grep – sed – sort – stat

    Utilizza ls – la pagina uomo ti dice come ordinare la directory.

     ls -clt | head -n 2 

    Il -n 2 è quindi non ottieni il "totale" nell'output. Se si desidera solo il nome del file.

     ls -t | head -n 1 

    E se avete bisogno dell'elenco nell'ordine normale (ottenendo il file più recente)

     ls -tr | head -n 1 

    Molto più facile che utilizzare la ricerca, molto più veloce e più robusto – non wherete preoccuparvi dei formati di denominazione dei file. Dovrebbe funzionare anche su quasi tutti i sisthemes.

    Sebbene la risposta accettata e gli altri fanno il lavoro, se si dispone di un tree molto grande, tutti saranno in grado di ordinare l'integer mazzo di file.

    Meglio se potessimo solo elencarli e tenere traccia dei più antichi, senza bisogno di ordinare affatto.

    Per questo ho scoperto questa soluzione alternativa:

     ls -lRU $PWD/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($1,0,1)=="/") { pat=substr($1,0,length($0)-1)"/"; }; if( $6 != "") {if ( $6 < oldd ) { oldd=$6; oldf=pat$8; }; print $6, pat$8; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}' 

    Spero che possa essere di qualsiasi aiuto, anche se la questione è un po 'vecchia.


    Modifica 1: queste modifiche consentono di analizzare file e directory con spazi. Il suo è abbastanza veloce da emetterlo nella root / e trovare il file più vecchio mai.

     ls -lRU --time-style=long-iso "$PWD"/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($0,0,1)=="/") { pat=substr($0,0,length($0)-1)"/"; $6="" }; if( $6 ~ /^[0-9]+$/) {if ( $6 < oldd ) { oldd=$6; oldf=$8; for(i=9; i<=NF; i++) oldf=oldf $i; oldf=pat oldf; }; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}' 

    Comando spiegato:

    • ls -lRU – time-style = long-iso "$ PWD" / * elenca tutti i file (*), long format (l), ricorsivamente (R), senza ordinare (U)
    • Awk poi BEGIN azzerando il contatore (facoltativo a questa domanda) e impostando la data di vecchia data di oggi, formatta l'AnnoMonthDay.
    • Prima il ciclo principale
      • Afferra il sesto field, la data, il formato Anno-Mese-Giorno e lo modifica in AnnoMonthDay (se il tuo output non viene visualizzato in questo modo, potrebbe essere necessario ottimizzare).
      • Utilizzando ricorsivi, ci saranno linee di intestazione per tutte le directory, sotto forma di / directory / qui :. Afferra questa linea in variabile pat. (sostituendo l'ultima ":" a "/"). E imposta $ 6 a nulla per evitare di utilizzare la linea di intestazione come una linea di file valida.
      • se il field $ 6 ha un numero valido, è una data. Confronta con la vecchia data oldd.
      • È più vecchio? Quindi salvare i nuovi valori per la vecchia data vecchia e il vecchio file di nome vecchio. BTW, oldf non è solo l'ottavo field, ma dall'8 alla fine. Ecco perché un ciclo da concatenare dall'8 al NF (fine).
      • Il count avanza da uno
      • END printingndo il risultato

    Esecuzione:

    ~ $ tempo ls -RU "$ PWD" / * | awk ecc.

    Data più vecchia: 19691231

    File: /home/…/…/backupold/…/EXAMPLES/how-to-program.txt

    Totale confronto: 111438

    reale 0m1.135s

    utente 0m0.872s

    sys 0m0.760s


    EDIT 2: Stesso concetto, soluzione migliore utilizzando find per guardare l' ora di accesso (utilizzare %T con il primo printf per il tempo di modifica o %C per la modifica dello stato ).

     find . -wholename "*" -type f -printf "%AY%Am%Ad %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}' 

    EDIT 3: Il command mugge usa il tempo di modifica e printing progressi incrementali in quanto trova file vecchi e vecchi, utile quando si dispone di alcuni timestamps errati (come 1970-01-01):

     find . -wholename "*" -type f -printf "%TY%Tm%Td %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; print oldd " " oldf; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}' 
     find ! -type d -printf "%T@ %p\n" | sort -n | head -n1 

    Sembra che da "più vecchie" la maggior parte delle persone abbia assunto che si intendesse "il tempo di modifica più antico". Questo è probabilmente corretto, secondo l'interpretazione più rigorosa di "più vecchio", ma se volevi quello con il tempo di accesso più antico, modificherò la risposta migliore così:

     find -type f -printf '%A+ %p\n' | sort | head -n 1 

    Si noti il %A+ .

     set $(find /search/dirname -type f -printf '%T+ %h/%f\n' | sort | head -n 1) && echo $2 
    • find ./search/dirname -type f -printf '%T+ %h/%f\n' printing le date ei nomi di file in due colonne.
    • sort | head -n1 sort | head -n1 mantiene la row corrispondente al file più vecchio.
    • echo $2 visualizza la seconda colonna, vale a dire il nome del file.
    Siamo il genio del computer e della rete.