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

Author: mwfearnley, 2010-12-30

19 answers

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

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

%T@ le da la hora 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.

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

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

 308
Author: plundra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-30 11:01:06

Siguiendo la respuesta de @plundra , aquí está la versión de BSD y OS X:

find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
 113
Author: Emerson Farrugia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:33

En lugar de ordenar los resultados y mantener solo los últimos modificados, podría usar awk para imprimir solo el que tenga 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 el número 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 (incluyendo espacio y nueva línea) pero eso.

Si no tiene tales nombres de archivo patológicos en su sistema también puedes 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.

 14
Author: marco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-28 14:11:30

Tuve el problema de encontrar el último archivo modificado bajo Solaris 10. Allí find no tiene la opción printf 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 del 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 lista todos los archivos
  • sed 's/.*/"&"/' envuelve 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 se asegura de que se devuelve una marca de tiempo completa (format year-month-day hour-minute-seconds-nanosegonds)
  • awk '{ print $6," ",$7 }' extrae solo la fecha y la hora
  • awk '{ print $6," ",$7," ",$9 }' extrae la fecha, la hora y el nombre del archivo
  • sort devuelve los archivos ordenados por fecha
  • tail -1 devuelve solo el último archivo modificado
 9
Author: Florian Feldhaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-05 16:08:45

Esto parece funcionar bien, incluso con subdirectorios:

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

En caso de demasiados archivos, refine la búsqueda.

 9
Author: mgratia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-29 16:19:03

Muestra el último archivo con la 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 por un número mayor

 6
Author: Fabian Schmengler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-08 08:50:46

Esto da una lista ordenada:

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

Invierta el orden colocando un '-r' en el comando sort. Si solo desea nombres de archivo, inserte " awk '{print 1 11} | / "antes de' / head '

 4
Author: Karlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-30 15:27:21

En Ubuntu 13, lo siguiente lo hace, tal vez un poco más rápido, ya que invierte el tipo y usa 'head' en lugar de 'tail', reduciendo el trabajo. Para mostrar los 11 archivos más recientes en un árbol:

Encontrar . - escriba f-printf '%T@ % p \ n '| sort-n-r | head -11 | cut-f2- -d" "| sed-e ' s,^./ ,, "/xargs ls-U-l

Esto da una lista completa de ls sin volver a ordenar y omite el molesto './ 'que' find ' pone en cada nombre de archivo.

O, como un bash función:

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 hecho por la solución original de plundra. Gracias plundra.

 3
Author: RickyS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-14 13:23:15

Esto cambia recursivamente el tiempo de modificación de todos los directorios en el directorio actual al archivo más reciente 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
 2
Author: rwhirn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-06 00:20:50

Este cli simple también funcionará:

ls -1t | head -1

Puede cambiar el -1 al número de archivos que desea listar

 2
Author: Ankit Zalani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-05 09:39:13

Me enfrenté al 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 recursivamente y busca en este directorio, etc.

 2
Author: AnatomicJC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-29 14:47:33

Uso algo similar todo el tiempo, así como la lista top-k de los archivos modificados más recientemente. Para árboles de directorios grandes, puede ser mucho más rápido para evitar ordenar. En el caso de solo top-1 archivo 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.4 s, una velocidad de 7.5 x contra la solución de 25.5 s usando sort.

 2
Author: Pierre D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-15 22:52:12

Si ejecutar stat en cada archivo individualmente es ralentizar, puede 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" " 
 1
Author: Mattias Wadman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-10 12:08:08

Encontré útil el comando anterior, pero para mi caso necesitaba ver la fecha y la hora del archivo, así que 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
 1
Author: Roger Cable,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-17 15:08:53

El siguiente comando funcionó en Solaris:

find . -name "*zip" -type f | xargs ls -ltr | tail -1 
 1
Author: RahulM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-23 12:30:42

Prefiero este, es más corto:

find . -type f -print0|xargs -0 ls -drt|tail -n 1
 0
Author: user3295940,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-11 06:36:21

Escribí un paquete pypi/github para esta pregunta porque también necesitaba una solución.

Https://github.com/bucknerns/logtail

Instalar:

pip install logtail

Uso: tails cambió archivos

logtail <log dir> [<glob match: default=*.log>]

Usage2: Abre el último archivo modificado en el editor

editlatest <log dir> [<glob match: default=*.log>]
 0
Author: Nathan Buckner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-12 19:05:48

Ignorando archivos ocultos-con una marca de tiempo agradable y rápida

Maneja los espacios en los nombres de archivo no que se deben utilizar aquellos!

$ 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

Más find galore se puede encontrar siguiendo el enlace.

 0
Author: Serge Stroobandt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-28 06:35:19

Encuentro la siguiente salida más corta y con más interpretable:

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

Dada la longitud fija de las fechas del formato ISO estandarizado, la ordenación lexicográfica está bien y no necesitamos la opción -n en la ordenación.

Si desea eliminar las marcas de tiempo de nuevo, puede utilizar:

find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
 0
Author: snth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-07 14:26:32