Sembra che ls
non ordina i file correttamente quando si effettua una chiamata ricorsiva:
ls -altR . | head -n 3
Come posso trovare il file modificato più di recente in una directory (comprese le sottodirectory)?
Sembra che ls
non ordina i file correttamente quando si effettua una chiamata ricorsiva:
ls -altR . | head -n 3
Come posso trovare il file modificato più di recente in una directory (comprese le sottodirectory)?
Risposte:
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Per un albero enorme, potrebbe essere difficile sort
mantenere tutto in memoria.
%T@
ti dà il tempo di modifica come un timestamp unix, sort -n
ordina numericamente, tail -1
prende l'ultima riga (timestamp più alto), cut -f2 -d" "
taglia il primo campo (timestamp) dall'output.
Modifica: Proprio come -printf
probabilmente è solo GNU, anche l'uso ajreals stat -c
è. Sebbene sia possibile fare lo stesso su BSD, le opzioni per la formattazione sono diverse (-f "%m %N"
sembrerebbe)
E mi mancava la parte del plurale; se volete più allora l' ultimo file, basta urtare l'argomento coda.
sort -rn | head -3
invece di sort -n | tail -3
. Una versione fornisce i file dal più vecchio al più recente, mentre l'altra passa dal più recente al più vecchio.
sort
creerà file temporanei (in /tmp
) in base alle necessità, quindi non credo sia una preoccupazione.
-printf '%T@ %Tb %Td %TY %p\n'
ti darà un timbro data (se necessario) (simile a ls
)
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Seguendo la risposta di @ plundra , ecco la versione di BSD e OS X:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
find
supporta +
invece di \;
? Perché fa la stessa cosa (passando più file come parametri), senza -print0 | xargs -0
pipe.
head -1
inhead -5
Invece di ordinare i risultati e conservare solo gli ultimi modificati, è possibile utilizzare awk per stampare solo quello con il tempo di modifica maggiore (in tempo unix):
find . -type f -printf "%T@\0%p\0" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\0'
Questo dovrebbe essere un modo più veloce per risolvere il tuo problema se il numero di file è abbastanza grande.
Ho usato il carattere NUL (cioè '\ 0') perché, in teoria, un nome file può contenere qualsiasi carattere (inclusi spazio e newline) tranne quello.
Se non hai tali nomi di file patologici nel tuo sistema, puoi usare anche il carattere di nuova riga:
find . -type f -printf "%T@\n%p\n" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\n'
Inoltre, funziona anche nel mawk.
mawk
l'alternativa standard Debian.
Ho avuto il problema di trovare l'ultimo file modificato in Solaris 10. Non find
esiste l' printf
opzione e stat
non è disponibile. Ho scoperto la seguente soluzione che funziona bene per me:
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1
Per mostrare anche il nome file, utilizzare
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Spiegazione
find . -type f
trova ed elenca tutti i filesed 's/.*/"&"/'
racchiude il percorso tra virgolette per gestire gli spazi bianchixargs ls -E
invia il percorso citato a ls
, l' -E
opzione si assicura che un timestamp completo (formato anno-mese-giorno ora-minuto-secondi-nanosecondi venga restituito )awk '{ print $6," ",$7 }'
estrae solo data e oraawk '{ print $6," ",$7," ",$9 }'
estrae data, ora e nome filesort
restituisce i file ordinati per datatail -1
restituisce solo l'ultimo file modificatoQuesto sembra funzionare bene, anche con le sottodirectory:
find . -type f | xargs ls -ltr | tail -n 1
In caso di troppi file, perfeziona la ricerca.
-l
opzione ls
sembra non necessaria. Proprio -tr
sembra sufficiente.
find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
Mostra l'ultimo file con data / ora leggibile dall'uomo:
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
Il risultato è simile al seguente:
2015-10-06 11:30: +0200 ./foo/bar.txt
Per mostrare più file, sostituiscilo -n1
con un numero più alto
Uso sempre qualcosa di simile, così come l'elenco top-k degli ultimi file modificati. Per alberi di directory di grandi dimensioni, può essere molto più veloce per evitare l'ordinamento . Nel caso del solo file 1 modificato più di recente:
find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
Su una directory contenente 1,7 milioni di file, ottengo il più recente in 3.4s, una velocità di 7.5x rispetto alla soluzione di 25.5s usando sort.
lastfile
) e quindi puoi fare quello che vuoi con il risultato, come ls -l $(lastfile .)
, o open $(lastfile .)
(su un Mac), ecc.
Su Ubuntu 13, ciò che segue lo fa, forse un po 'più veloce, poiché inverte l'ordinamento e usa' testa 'invece di' coda ', riducendo il lavoro. Per mostrare gli 11 file più recenti in un albero:
trova . -type f -printf '% T @% p \ n' | ordina -n -r | testa -11 | cut -f2- -d "" | sed -e 's, ^. / ,,' | xargs ls -U -l
Questo fornisce un elenco completo di ls senza riordinamento e omette il fastidioso './' che 'find' inserisce ogni nome di file.
Oppure, come funzione bash:
treecent () {
local numl
if [[ 0 -eq $# ]] ; then
numl=11 # Or whatever default you want.
else
numl=$1
fi
find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} | cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}
Tuttavia, gran parte del lavoro è stato svolto dalla soluzione originale di Plundra. Grazie plundra.
Ho affrontato lo stesso problema. Devo trovare ricorsivamente il file più recente. trovare ha impiegato circa 50 minuti per trovare.
Ecco un piccolo script per farlo più velocemente:
#!/bin/sh
CURRENT_DIR='.'
zob () {
FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
if [ ! -f ${FILE} ]; then
CURRENT_DIR="${CURRENT_DIR}/${FILE}"
zob
fi
echo $FILE
exit
}
zob
È una funzione ricorsiva che ottiene l'elemento modificato più recente di una directory. Se questo elemento è una directory, la funzione viene chiamata ricorsivamente e cerca in questa directory, ecc.
Trovo il seguente output più breve e con più interpretabile:
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Data la lunghezza fissa dei tempi di trasmissione standardizzati del formato ISO, l'ordinamento lessicografico va bene e non abbiamo bisogno -n
dell'opzione sull'ordinamento .
Se si desidera rimuovere nuovamente i timestamp, è possibile utilizzare:
find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
Se l'esecuzione stat
su ogni file singolarmente è un rallentamento, puoi usare xargs
per accelerare un po 'le cose:
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
Ciò modifica in modo ricorsivo il tempo di modifica di tutte le directory nella directory corrente nel file più recente in ciascuna directory:
for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done
Questo semplice cli funzionerà anche:
ls -1t | head -1
È possibile modificare -1 per il numero di file che si desidera elencare
Ho trovato utile il comando sopra, ma per il mio caso avevo bisogno di vedere anche la data e l'ora del file e ho avuto un problema con diversi file con spazi nei nomi. Ecco la mia soluzione di lavoro.
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10
Gestisce bene gli spazi nei nomi dei file - non che questi debbano essere usati!
2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht
Più a find
bizzeffe seguendo il link.
Per cercare i file in / target_directory e tutte le sue sottodirectory, che sono state modificate negli ultimi 60 minuti:
$ find /target_directory -type f -mmin -60
Per trovare i file modificati più di recente, ordinati in ordine inverso rispetto al tempo di aggiornamento (ovvero, i file aggiornati più di recente per primi):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
Preferisco questo, è più corto:
find . -type f -print0|xargs -0 ls -drt|tail -n 1
Ho scritto un pacchetto pypi / github per questa domanda perché avevo bisogno anche di una soluzione.
https://github.com/bucknerns/logtail
Installare:
pip install logtail
Uso: tails ha cambiato i file
logtail <log dir> [<glob match: default=*.log>]
Usage2: Apre l'ultimo file modificato nell'editor
editlatest <log dir> [<glob match: default=*.log>]