¿Cómo encontrar recursivamente el último archivo modificado en un directorio?

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)?

 find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " 

Para un árbol enorme, puede ser difícil para sort todo en la memoria.

%T@ le da el tiempo de modificación como una marca de tiempo de unix, sort -n ordena numéricamente, tail -1 toma la última línea (marca de hora más alta), cut -f2 -d" " corta el primer campo (marca de tiempo) de la salida .

Editar: Así como ” -printf es probablemente solo GNU, el uso de stat -c ajreals también. Aunque es posible hacer lo mismo en BSD, las opciones para formatear son diferentes ( -f "%m %N" , parecería)

Y me perdí la parte del plural; si quieres más que el último archivo, simplemente aumenta el argumento de la cola.

Siguiendo 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" " 

En lugar de clasificar 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 (incluidos el espacio y la línea nueva), pero eso.

Si no tiene esos nombres de archivo patológicos en su sistema, también puede usar el carácter de línea nueva:

 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.

Tuve el problema de encontrar el último archivo modificado en Solaris 10. Allí no tiene la opción printf y la 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 find . -type f encuentra y enumera todos los archivos
  • sed 's/.*/"&"/' ajusta el nombre de ruta entre comillas para manejar espacios en blanco
  • xargs ls -E envía la ruta citada a ls , la opción -E asegura que se devuelve una marca de tiempo completa (formato año-mes-día hora-minuto-segundos-nanosegundos )
  • awk '{ print $6," ",$7 }' extrae solo fecha y hora
  • awk '{ print $6," ",$7," ",$9 }' extrae fecha, hora y nombre del archivo
  • sort devuelve los archivos ordenados por fecha
  • tail -1 devuelve solo el último archivo modificado

Esto parece funcionar bien, incluso con subdirectorios:

 find . -type f | xargs ls -ltr | tail -n 1 

En caso de que haya demasiados archivos, refine el hallazgo.

Muestra el último archivo con marca de tiempo legible por 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, reemplace -n1 con un número más alto

Esto le da una lista ordenada:

 find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5 

Invierta el orden colocando ‘-r’ en el comando de ordenación. Si solo quiere nombres de archivos, inserte “awk” {print $ 11} ‘| ” antes ‘| cabeza’

En Ubuntu 13, lo siguiente, quizás un poco más rápido, ya que invierte el orden y usa ‘cabeza’ en vez de ‘cola’, reduciendo el trabajo. Para mostrar los 11 archivos más nuevos en un árbol:

encontrar . -type f -printf ‘% T @% p \ n’ | ordenar -n -r | cabeza -11 | cut -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’ coloca en cada nombre de archivo.

O bien, 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.

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 a la cantidad de archivos que desea enumerar

Enfrenté el mismo problema. Necesito encontrar el archivo más reciente recursivamente. 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.

Uso algo similar todo el tiempo, así como también la lista top-k de los archivos modificados más recientemente. Para grandes árboles de directorios, puede ser mucho más rápido evitar la clasificación . En el caso del archivo recientemente modificado de top-1:

 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.

Si ejecutar stat en cada archivo individualmente es lento, puedes usar xargs para acelerar un poco las cosas:

 find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" " 

Encontré útil el comando anterior, pero para mi caso necesitaba ver la fecha y la hora del archivo y 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 

El siguiente comando funcionó en Solaris:

 find . -name "*zip" -type f | xargs ls -ltr | tail -1 

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 necesitaba una solución también.

https://github.com/bucknerns/logtail

Instalar:

 pip install logtail 

Uso: las colas han cambiado los archivos

 logtail  [] 

Uso2: abre el último archivo modificado en el editor

 editlatest  [] 

Ignorar archivos ocultos, con una marca de tiempo agradable y rápida

Maneja bien los espacios en los nombres de archivo, ¡no es que deba usarlos!

 $ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10 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 

Puede find más en abundancia siguiendo el enlace.

Encuentro los siguientes resultados más cortos y con más interpretables:

 find . -type f -printf '%TF %TT %p\n' | sort | tail -1 

Dada la longitud fija de las fechas de formato ISO estandarizadas, la clasificación lexicográfica está bien y no necesitamos la opción -n en el género.

Si desea eliminar las marcas de tiempo nuevamente, puede usar:

 find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '