Unix / Linux buscar y ordenar por fecha de modificación

111

¿Cómo puedo hacer un simple find ¿Cuál sería el orden de los resultados modificados más recientemente?

Aquí está la corriente find Estoy usando (estoy haciendo un escape de shell en PHP, así que ese es el razonamiento de las variables):

find '$dir' -name '$str'\* -print | head -10

¿Cómo podría tener este pedido la búsqueda por última modificación? (Tenga en cuenta que no quiero que se clasifique después de la búsqueda, sino que busque los resultados según lo que se modificó más recientemente).

Peter Mortensen
fuente
github.com/shadkam/recentmost Haría lo que se desea, pero uno necesita construirlo.
user3392225

Respuestas:

116

Utilizar esta:

find . -printf "%T@ %Tc %p\n" | sort -n

printf argumentos de man find:

  • %Tk: Última hora de modificación del archivo en el formato especificado por k.

  • @: segundos desde el 1 de enero de 1970, 00:00 GMT, con parte fraccionaria.

  • c: fecha y hora del local (sáb 04 nov 12:02:33 EST 1989).

  • %p: Nombre del archivo.

user195696
fuente
5
+1 Muy útil, la primera respuesta a esto encontré con un resultado de fecha legible / útil
Jake N
más confiable (y muy simple) ya que el tiempo se concede para ser numéricamente secuencial (por lo tanto, siempre ordenable), gracias!
Aquarius Power
1
Tengo este alias para encontrar archivos recientes en mi ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; } Encuentra recursivamente todos los archivos que contienen el patrón del primer argumento pasado al comando ( fr <pattern> ) y los clasifica con el último más reciente.
joelostblom
4
por ISO 8601 fecha de salida, uso find . -printf "%T@ %CY-%Cm-%CdT%CH:%CM:%CS %p\n" | sort -n. Como se clasifica de forma natural, también se puede usar directamente en la clasificación: find . -printf "%CY-%Cm-%CdT%CH:%CM:%CS %p\n" | sort -n
Peter Mortensen
@PeterMortensen buen comentario pero el tuyo no incluye la zona horaria ...
Steven Lu
80

El método más sencillo es usar zsh, gracias a su clasificatorios globales .

print -lr -- $dir/**/$str*(om[1,10])

Si tiene una búsqueda GNU, haga que imprima los tiempos de modificación del archivo y ordénelos por orden.

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

Si tiene GNU find pero no otras utilidades de GNU, use nuevas líneas como separadores en lugar de nulos; perderá soporte para los nombres de archivo que contienen nuevas líneas.

find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10

Si tiene Perl (aquí asumiré que no hay nuevas líneas en los nombres de archivo):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_;  # sort by increasing age
        print @sorted[0..9];
    }'

Si tiene Python (también asumiendo que no hay nuevas líneas en los nombres de archivo):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f], reverse=True))[:10]: print f'

Probablemente hay una manera de hacer lo mismo en PHP, pero no lo sé.

Si quieres trabajar solo con herramientas POSIX, es bastante más complicado; ver Cómo listar los archivos ordenados por fecha de modificación de forma recursiva (¡no hay un comando de estadísticas disponible!) (repatinar los primeros 10 es la parte fácil).

Gilles
fuente
creo que el find La versión muestra los archivos más antiguos, y que necesita agregar el -r opción a sort.
Quentin Pradet
Mi sed dice que no tiene una opción -z.
Kef Schecter
@KefSchecter Luego use las nuevas líneas como separadores, pero perderá la compatibilidad con las nuevas líneas en los nombres de los archivos.
Gilles
Lo anterior es para python2. Si solo tienes python3, algunos pequeños cambios: python3 -c 'import os, sys; veces = {} para f en sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime para f in (ordenados (times.keys (), key = lambda f: times [f], reverse = True)) [: 10]: print (f); '
Neil McGill
36

No necesitas PHP ni Python, solo ls :

man ls:
-t     sort by modification time
-r,    reverse order while sorting (--reverse )
-1     list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Si el comando * sale con un estado de falla (es decir, Lista de argumentos demasiado larga ), entonces puedes iterar con encontrar. Parafraseado de: La longitud máxima de los argumentos para un nuevo proceso.

  • find . -print0|xargs -0 command (optimiza la velocidad, si find no implementa "-exec +" pero sabe "-print0")
  • find . -print|xargs command (Si no hay espacio en blanco en los argumentos)

Si la mayor parte de los argumentos consiste en rutas largas, absolutas o relativas, intente mover sus acciones al directorio: cd /directory/with/long/path; command * Y otra solución rápida puede ser unir menos argumentos: command [a-e]*; command [f-m]*; ...

Ярослав Рахматуллин
fuente
1
Si hay muchos archivos, esto falla con 'Lista de argumentos demasiado larga' en la ls.
occulus
1
Eso es cierto, pero creo que la pregunta era "¿Cómo puedo hacer un simple hallazgo ..."
Ярослав Рахматуллин
2
ls no cita los nombres de los archivos de forma que los xargs puedan entender (no hay opción -0, y los distintos estilos de cita son inadecuados)
Tobu
10

Solo necesitas ls

Podrías hacerlo find /wherever/your/files/hide -type f -exec ls -1rt "{}" +; como se indicó anteriormente,

o

ls -1rt `find /wherever/your/file/hides -type f`
skippy1910
fuente
2
Si hay muchos archivos, esto falla con 'Lista de argumentos demasiado larga' en la ls. Tal vez recook para utilizar xargs?
occulus
1
Pero si xargs llamadas ls Varias veces, la clasificación se romperá.
Aaron D. Marasco
Esto falla para archivos con espacios en sus nombres. ¿Algún consejo?
user74094
5

Extensible La respuesta de user195696 :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Para cada archivo, este primero genera la marca de tiempo numérica (para ordenar por, seguido de tabulación \t ), luego una marca de tiempo legible por humanos, luego el tamaño del archivo (desafortunadamente find es -printf no se puede hacer en mebibytes, solo kibibytes), luego el nombre del archivo con la ruta relativa.

Entonces sort -n lo ordena por el primer campo numérico.

Entonces cut se deshace de ese primer campo numérico que no es de interés para el usuario. (Imprime el segundo campo hacia adelante.) El separador de campo predeterminado es \t o la tabulación.

Ejemplo de salida:

Thu 06 Feb 2014 04:49:14 PM EST     64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST      0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST     64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST      0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST     64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST   9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST   9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST   9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST     32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST      0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST  70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST  70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST  70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST      0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST     32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST     32 KiB ./plot_grid.m

Hice deliberadamente el tamaño del archivo de 6 caracteres, porque si lo hace más largo, es difícil distinguir visualmente qué tan grandes son los archivos. De esta manera, los archivos de más de 1e6 KiB sobresalen: por 1 char significa 1-9 GB, por 2 caracteres significa 10-99 GB, etc.


Edición: aquí hay otra versión (desde find . -printf "%Tc" se bloquea en MinGW / MSYS):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Dando salida como:

-rw-r--r-- 1 es 23K Jul 10  2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Dónde:

  • -I{} causa la ocurrencia de {} para ser reemplazado por un argumento, y las nuevas líneas son ahora los separadores de argumentos (tenga en cuenta los espacios en los nombres de archivo anteriores).

  • ls -G suprime la impresión del nombre del grupo (pérdida de espacio).

  • ls -h --si produce tamaños de archivo legibles para el ser humano (más correctos con --si ).

  • ls -t ordena por tiempo, lo cual es irrelevante aquí, pero eso es lo que normalmente uso.

Evgeni Sergeev
fuente
1
Nota: ordenar por archivo tamaño en su lugar, simplemente reemplace el T@ por s en cualquiera de los comandos anteriores.
Evgeni Sergeev
2

Variante de OS X de la respuesta de @ user195696:

  1. Con marca de tiempo:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. Sin marca de tiempo:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    
user9399
fuente
1

Descubrí que esto hace el trabajo en Mac OS X (y lo suficientemente genérico para trabajar en otros Unixen también):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
Bryan Petty
fuente
2
Lamentablemente, esto imprime los nombres de los meses localizados en mi configuración croata, haciendo que la clasificación sea incorrecta.
Ivan Vučica
La respuesta de user195696 Trabajos para la configuración croata (y otros).
Peter Mortensen
1

Si tu find La selección es muy simple, puede prescindir de ella, y simplemente usar ls:

ls -1 *.cc # -r -t optional
djc
fuente
1

Tratar:

find '$dir' -name '$str'\* -print | xargs ls -tl | head -10

Pero también es útil filtrar los datos por -mmin / -mtime y -type.

Peter Mortensen
fuente
1

Utilizar:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

Este comando ordenará los archivos por fecha de modificación.

Y mostrar como

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
Akash
fuente
He mejorado este texto para manejar espacios en blanco en los nombres de archivo, ver superusuario.com/a/777007/134532
jan
0

No pienso find Tiene alguna opción para modificar el orden de salida. -mtime y -mmin le permitirá restringir los resultados a los archivos que se han modificado dentro de una ventana de tiempo determinada, pero la salida no se ordenará, tendrá que hacerlo usted mismo. ÑU find tiene un -printf opción que, entre otras cosas, le permitirá imprimir la hora de modificación de cada archivo encontrado (cadenas de formato) %t o %Tk ); Eso podría ayudarte a ordenar el find Salida de la manera que desee.

Jim Lewis
fuente
0

Mejoré la respuesta de Akashs haciendo que el script manejara espacios en blanco en los nombres de archivos correctamente:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';
jan
fuente
0

Si quieres ordenar todos los archivos PNG por tiempo en $PWD:

Este sencillo de una sola línea da toda la flexibilidad de la expresión regular en find y en ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
john smith
fuente
0

Puedes usar stat en BSD y Linux (no en POSIX) de esta manera:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

Si quieres limitar el número:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-
drewk
fuente
-1

Si solo desea obtener una ruta completa de cada elemento, puede anotar así.

 find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

Dónde
-printf "% T @% p \ n" para dar criterios de clasificación (fecha),
'sort -nr' para clasificar por fecha,
cabeza -10 para listar los 10 mejores resultados,
corte -d '' -f 2 para cortar la marca de tiempo principal en cada línea.

David Jung
fuente
-3

Tengo una solución simple.

Después cd a un directorio, usar

find . -iname "*" -ls

sing
fuente
1
Esto no se ordena por fecha de modificación.
DavidPostill