Parece que ls
no ordena los archivos correctamente al hacer una llamada recursiva:
ls -altR . | head -n 3
¿Cómo puedo encontrar el archivo modificado más recientemente en un directorio (incluidos los subdirectorios)?
Parece que ls
no ordena los archivos correctamente al hacer una llamada recursiva:
ls -altR . | head -n 3
¿Cómo puedo encontrar el archivo modificado más recientemente en un directorio (incluidos los subdirectorios)?
Respuestas:
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "
Para un árbol enorme, puede ser difícil sort
mantener todo en la memoria.
%T@
le da el tiempo de modificación como una marca de tiempo unix, sort -n
ordena numéricamente, tail -1
toma la última línea (marca de tiempo más alta), cut -f2 -d" "
corta el primer campo (la marca de tiempo) de la salida.
Editar: al igual que -printf
probablemente sea solo GNU, también se usa un uso real de stat -c
. Aunque es posible hacer lo mismo en BSD, las opciones para formatear son diferentes ( -f "%m %N"
parece)
Y me perdí la parte del plural; si quieres más que el último archivo, solo sube el argumento de cola.
sort -rn | head -3
lugar de sort -n | tail -3
. Una versión proporciona los archivos del más antiguo al más nuevo, mientras que la otra va del más nuevo al más antiguo.
sort
creará archivos temporales (en /tmp
) según sea necesario, por lo que no creo que sea una preocupación.
-printf '%T@ %Tb %Td %TY %p\n'
le dará un sello de fecha (si es necesario) (similar a ls
)
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Siguiendo con la respuesta de @ plundra , aquí está la versión BSD y OS X:
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
find
admite en +
lugar de \;
? Porque eso hace lo mismo (pasar múltiples archivos como parámetros), sin la -print0 | xargs -0
tubería.
head -1
ahead -5
En lugar de ordenar los resultados y conservar solo los últimos modificados, puede usar awk para imprimir solo el que tenga el mayor tiempo de modificación (en tiempo unix):
find . -type f -printf "%T@\0%p\0" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\0'
Esta debería ser una forma más rápida de resolver su problema si la cantidad de archivos es lo suficientemente grande.
He usado el carácter NUL (es decir, '\ 0') porque, teóricamente, un nombre de archivo puede contener cualquier carácter (incluido el espacio y la nueva línea) pero eso.
Si no tiene esos nombres de archivo patológicos en su sistema, también puede usar el carácter de nueva línea:
find . -type f -printf "%T@\n%p\n" | awk '
{
if ($0>max) {
max=$0;
getline mostrecent
} else
getline
}
END{print mostrecent}' RS='\n'
Además, esto también funciona en mawk.
mawk
la alternativa estándar de Debian.
Tuve el problema de encontrar el último archivo modificado en Solaris 10. No find
tiene la printf
opción y stat
no está disponible. Descubrí la siguiente solución que funciona bien para mí:
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1
Para mostrar el nombre de archivo también use
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
Explicación
find . -type f
encuentra y enumera todos los archivossed 's/.*/"&"/'
ajusta el nombre de ruta entre comillas para manejar espacios en blancoxargs ls -E
envía la ruta entre comillas ls
, la -E
opción asegura que se devuelva una marca de tiempo completa (formato año-mes-día hora-minuto-segundos-nanosegundos )awk '{ print $6," ",$7 }'
extrae solo fecha y horaawk '{ print $6," ",$7," ",$9 }'
extrae fecha, hora y nombre de archivosort
devuelve los archivos ordenados por fechatail -1
devuelve solo el último archivo modificadoEsto parece funcionar bien, incluso con subdirectorios:
find . -type f | xargs ls -ltr | tail -n 1
En caso de demasiados archivos, refine el hallazgo.
-l
opción de ls
parece innecesaria. Solo -tr
parece suficiente.
find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
Muestra el último archivo con marca de tiempo legible para humanos:
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
El resultado se ve así:
2015-10-06 11:30: +0200 ./foo/bar.txt
Para mostrar más archivos, reemplácelos -n1
por un número mayor
Uso algo similar todo el tiempo, así como la lista de top-k de los archivos modificados más recientemente. Para árboles de directorios grandes, puede ser mucho más rápido evitar la ordenación . En el caso de solo el archivo top-1 modificado más recientemente:
find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
En un directorio que contiene 1.7 millones de archivos, obtengo el más reciente en 3.4s, una aceleración de 7.5x contra la solución de 25.5s usando sort.
lastfile
) y luego puede hacer lo que quiera con el resultado, como ls -l $(lastfile .)
, o open $(lastfile .)
(en una Mac), etc.
En Ubuntu 13, lo siguiente lo hace, tal vez un poco más rápido, ya que invierte el orden y usa 'cabeza' en lugar de 'cola', lo que reduce el trabajo. Para mostrar los 11 archivos más nuevos en un árbol:
encontrar . -tipo f -printf '% T @% p \ n' | ordenar -n -r | cabeza -11 | cortar -f2- -d "" | sed -e 's, ^. / ,,' | xargs ls -U -l
Esto proporciona una lista completa de ls sin volver a ordenar y omite el molesto './' que 'find' pone en cada nombre de archivo.
O, como una función 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
}
Aún así, la mayor parte del trabajo fue realizado por la solución original de plundra. Gracias plundra
Me enfrenté al mismo problema. Necesito encontrar el archivo más reciente de forma recursiva. encontrar tomó alrededor de 50 minutos para encontrar.
Aquí hay un pequeño script para hacerlo más rápido:
#!/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
Es una función recursiva que obtiene el elemento modificado más reciente de un directorio. Si este elemento es un directorio, la función se llama de forma recursiva y busca en este directorio, etc.
Encuentro lo siguiente más corto y con una salida más interpretable:
find . -type f -printf '%TF %TT %p\n' | sort | tail -1
Dada la longitud fija de las fechas y horas del formato ISO estandarizado, la clasificación lexicográfica está bien y no necesitamos la -n
opción en la clasificación.
Si desea eliminar las marcas de tiempo nuevamente, puede usar:
find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
Si ejecutar stat
cada archivo individualmente es lento, puede usarlo xargs
para acelerar un poco las cosas:
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
Esto cambia recursivamente el tiempo de modificación de todos los directorios en el directorio actual al archivo más nuevo en cada directorio:
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
Este simple cli también funcionará:
ls -1t | head -1
Puede cambiar el -1 al número de archivos que desea enumerar
Encontré el comando anterior útil, pero para mi caso también necesitaba ver la fecha y la hora del archivo, tuve un problema con varios archivos que tienen espacios en los nombres. Aquí está mi solución de trabajo.
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
Maneja bien los espacios en los nombres de archivo, ¡no es que se deban usar!
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
Más find
abundancia siguiendo el enlace.
Para buscar archivos en / target_directory y todos sus subdirectorios, que se han modificado en los últimos 60 minutos:
$ find /target_directory -type f -mmin -60
Para buscar los archivos modificados más recientemente, ordenados en el orden inverso del tiempo de actualización (es decir, los archivos actualizados más recientemente primero):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
Prefiero este, es más corto:
find . -type f -print0|xargs -0 ls -drt|tail -n 1
Escribí un paquete pypi / github para esta pregunta porque también necesitaba una solución.
https://github.com/bucknerns/logtail
Instalar en pc:
pip install logtail
Uso: colas cambiaron archivos
logtail <log dir> [<glob match: default=*.log>]
Uso2: abre el último archivo modificado en el editor
editlatest <log dir> [<glob match: default=*.log>]