por - listar ultimos archivos modificados linux
¿Cómo encontrar y listar recursivamente los últimos archivos modificados en un directorio con subdirectorios y tiempos? (16)
Sistema operativo: Linux
Tipo de sistema de archivos: ext3
Solución preferida: bash (script / oneliner), ruby, python
Tengo varios directorios con varios subdirectorios y archivos en ellos. Necesito hacer una lista de todos estos directorios que se construye de tal manera que cada directorio de primer nivel se encuentre junto a la fecha y hora del último archivo creado / modificado dentro de él.
Para aclarar, si toco un archivo o modifico su contenido a unos pocos niveles de subdirectorio hacia abajo, esa marca de tiempo debe aparecer junto al nombre del directorio de primer nivel. Digamos que tengo un directorio estructurado como este:
./alfa/beta/gamma/example.txt
y modifico el contenido del archivo example.txt
, necesito que la hora se muestre junto al directorio alfa
primer nivel en forma legible para los humanos, no en la época. He intentado algunas cosas utilizando find, xargs
, sort
y likes, pero no puedo solucionar el problema de que la marca de tiempo del sistema de archivos de ''alfa'' no cambia cuando creo / modifico los archivos unos niveles más abajo.
Ignorando archivos ocultos - con sello de tiempo agradable y rápido
Maneja bien los espacios en los nombres de archivo, ¡no es que debas usarlos!
$ find . -type f -not -path ''*//.*'' -printf ''%TY.%Tm.%Td %THh%TM %Ta %p/n'' |sort -nr |head -n 10
2017.01.28 07h00 Sat ./recent
2017.01.21 10h49 Sat ./hgb
2017.01.16 07h44 Mon ./swx
2017.01.10 18h24 Tue ./update-stations
2017.01.09 10h38 Mon ./stations.json
Más find
abundancia se puede encontrar siguiendo el enlace.
Acorté la asombrosa respuesta de Halo a esta frase única.
stat --printf="%y %n/n" $(ls -tr $(find * -type f))
Actualizado : si hay espacios en los nombres de archivo, puede utilizar esta modificación
OFS="$IFS";IFS=$''/n'';stat --printf="%y %n/n" $(ls -tr $(find . -type f));IFS="$OFS";
Aquí hay una versión que funciona con nombres de archivos que pueden contener espacios, nuevas líneas y también caracteres globales:
find . -type f -printf "%T@ %p/0" | sort -zk1nr
-
find ... -printf
imprime la modificación del archivo (valor EPOCH) seguido de un espacio y/0
nombres de archivo terminados. -
sort -zk1nr
lee los datos terminados en NUL y los ordena en orden numérico inverso
Como la pregunta está etiquetada con Linux, supongo que los gnu
utils están disponibles.
Puedes canalizar arriba con:
xargs -0 printf "%s/n"
para imprimir la hora de modificación y los nombres de archivo ordenados por la hora de modificación (la más reciente primero) terminada por líneas nuevas.
Este comando funciona en Mac OS X:
find "$1" -type f -print0 | xargs -0 stat --format ''%Y :%y %n'' | sort -nr | cut -d: -f2- | head
En Linux, como pidió el póster original, use stat
lugar de gstat
.
Esta respuesta es, por supuesto, la solución sobresaliente del user37078 , promovida del comentario a la respuesta completa. CharlesB la idea de gstat
utilizar gstat
en Mac OS X. Por gstat
, obtuve coreutils de MacPorts lugar de homebrew .
Y aquí es cómo empaqueté esto en un comando simple ~/bin/ls-recent.sh
para reutilizarlo:
#!/bin/bash
# ls-recent: list files in a dir tree, most recently modified first
#
# Usage: ls-recent path [-10 | more]
#
# Where "path" is a path to target directory, "-10" is any arg to pass
# to "head" to limit the number of entries, and "more" is a special arg
# in place of "-10" which calls the pager "more" instead of "head".
if [ "more" = "$2" ]; then
H=more; N=''''
else
H=head; N=$2
fi
find "$1" -type f -print0 |xargs -0 gstat --format ''%Y :%y %n'' /
|sort -nr |cut -d: -f2- |$H $N
Esto podría hacerse con una función reccursiva en bash también
Sea F una función que muestra la hora del archivo que debe ser lexicográficamente clasificable aaaa-mm-dd, etc. (¿dependiente del sistema?)
F(){ stat --format %y "$1";} # Linux
F(){ ls -E "$1"|awk ''{print$6" "$7}'';} # SunOS: maybe this could be done easier
R la función recursiva que se ejecuta a través de directorios
R(){ local f;for f in "$1"/*;do [ -d "$f" ]&&R $f||F "$f";done;}
Y finalmente
for f in *;do [ -d "$f" ]&&echo `R "$f"|sort|tail -1`" $f";done
Estoy mostrando esto para el último tiempo de acceso, puede modificarlo fácilmente para hacer el último tiempo de modificación.
Hay dos maneras de hacer esto:
1) Si desea evitar la clasificación global, que puede ser costosa si tiene decenas de millones de archivos, entonces puede hacerlo: (colóquese en la raíz del directorio donde desea que comience la búsqueda)
linux> touch -d @0 /tmp/a;
linux> find . -type f -exec tcsh -f -c test `stat --printf="%X" {}` -gt `stat --printf="%X" /tmp/a` ; -exec tcsh -f -c touch -a -r {} /tmp/a ; -print
El método anterior imprime los nombres de archivo con un tiempo de acceso progresivamente más nuevo y el último archivo que se imprime es el archivo con el último tiempo de acceso. Obviamente, puede obtener el último tiempo de acceso utilizando una "cola -1".
2) Puede hacer que encuentre de forma recursiva el nombre, el tiempo de acceso de todos los archivos en su subdirectorio y luego ordene según el tiempo de acceso y la cola la entrada más grande:
linux> /find . -type f -exec stat --printf="%X %n/n" {} /; | /sort -n | tail -1
Y ahí lo tienes...
Función bash rápida:
# findLatestModifiedFiles(directory, [max=10, [format="%Td %Tb %TY, %TT"]])
function findLatestModifiedFiles() {
local d="${1:-.}"
local m="${2:-10}"
local f="${3:-%Td %Tb %TY, %TT}"
find "$d" -type f -printf "%T@ :$f %p/n" | sort -nr | cut -d: -f2- | head -n"$m"
}
Encuentra el último archivo modificado en un directorio:
findLatestModifiedFiles "/home/jason/" 1
También puede especificar su propio formato de fecha / hora como tercer argumento.
GNU Find (ver man find
) tiene un parámetro -printf para mostrar los archivos EPOC mtime y el nombre de ruta relativo.
redhat> find . -type f -printf ''%T@ %P/n'' | sort -n | awk ''{print $2}''
Lo siguiente le devuelve una cadena de la marca de tiempo y el nombre del archivo con la marca de tiempo más reciente:
find $Directory -type f -printf "%TY-%Tm-%Td-%TH-%TM-%TS %p/n" | sed -r ''s/([[:digit:]]{2})/.([[:digit:]]{2,})//1-/2/'' | sort --field-separator=''-'' -nrk1 -nrk2 -nrk3 -nrk4 -nrk5 -nrk6 -nrk7 | head -n 1
Resultando en una salida de la forma: <yy-mm-dd-hh-mm-ss.nanosec> <filename>
Para encontrar todos los archivos en los que se modificó el estado del archivo hace N minutos:
find -cmin -N
por ejemplo:
find -cmin -5
Para una salida ls
simple, usa esto. No hay lista de argumentos, por lo que no puede ser demasiado larga:
find . | while read FILE;do ls -d -l "$FILE";done
Y agradable con cut
solo para las fechas, horas y nombre:
find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d '' '' -f 1-5
EDITAR : acaba de notar que la respuesta principal actual se ordena por fecha de modificación. Eso es igual de fácil con el segundo ejemplo aquí, ya que la fecha de modificación es la primera en cada línea; dé una palmada al final:
find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d '' '' -f 1-5 | sort
Prueba este:
#!/bin/bash
find $1 -type f -exec stat --format ''%Y :%y %n'' "{}" /; | sort -nr | cut -d: -f2- | head
Ejecútelo con la ruta al directorio donde debería comenzar a escanear recursivamente (admite nombres de archivo con espacios).
Si hay muchos archivos, puede tomar un tiempo antes de que devuelva algo. El rendimiento puede mejorarse si usamos xargs
lugar:
#!/bin/bash
find $1 -type f -print0 | xargs -0 stat --format ''%Y :%y %n'' | sort -nr | cut -d: -f2- | head
que es un poco más rápido.
Prueba esto
#!/bin/bash
stat --format %y $(ls -t $(find alfa/ -type f) | head -n 1)
Utiliza la función find
para recopilar todos los archivos del directorio, ls
para enumerarlos ordenados por fecha de modificación, head
para seleccionar el primer archivo y finalmente stat
para mostrar la hora en un formato agradable.
En este momento no es seguro para los archivos con espacios en blanco u otros caracteres especiales en sus nombres. Escribe una recomendación si aún no satisface tus necesidades.
Tanto las soluciones perl como Python en este post me ayudaron a resolver este problema en Mac OS X: https://unix.stackexchange.com/questions/9247/how-to-list-files-sorted-by-modification-date-recursively-no-stat-command-avail .
Citando desde el post:
Perl:
find . -type f -print |
perl -l -ne ''
$_{$_} = -M; # store file age (mtime - now)
END {
$,="/n";
print sort {$_{$b} <=> $_{$a}} keys %_; # print by decreasing age
}''
Pitón:
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]): print f''
Tengo este alias en mi .profile que uso bastante a menudo
$ alias | grep xlogs
xlogs=''sudo find . /( -name "*.log" -o -name "*.trc" /) -mtime -1 | sudo xargs ls -ltr --color | less -R''
Así que hace lo que está buscando (con la excepción de que no se modifica la fecha / hora en varios niveles): busca los archivos más recientes (archivos * .log y * .trc en este caso); También solo encuentra los archivos modificados en el último día, luego ordena por tiempo y canaliza la salida a través de menos:
sudo find . /( -name "*.log" -o -name "*.trc" /) -mtime -1 | sudo xargs ls -ltr --color | less -R
PD. Tenga en cuenta que no tengo root en algunos de los servidores, pero siempre tengo sudo, por lo que es posible que no necesite esa parte.
Usted puede dar el comando printf de encontrar un intento
El último tiempo de acceso de% Ak File en el formato especificado por k, que es
@'' or a directive for the C
strftime''. Los valores posibles para k se enumeran a continuación; Es posible que algunos de ellos no estén disponibles en todos los sistemas, debido a las diferencias en el "tiempo de respuesta" entre los sistemas.