¿Cómo enumerar los archivos que fueron cambiados en un cierto rango de tiempo?


38

¿Cómo puedo enumerar recursivamente todos los archivos que se cambiaron entre 22.12.2011 y 24.12.2011?


66
Si quiere decir 'último cambio', tiene la oportunidad de encontrar una solución. Si un archivo se modificó el 26.12.2011, no puede saber si también se modificó durante su rango dado. (A menos que tenga un sistema de archivos muy exótico.)
William Pursell

Respuestas:


25

En términos generales, cuando busca archivos en un directorio y sus subdirectorios de forma recursiva, use find.

La forma más fácil de especificar un rango de fechas findes crear archivos en los límites del rango y usar el -newerpredicado.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop

¿Por qué -newerse necesita negar la salida del primero aquí?
Alexander Cska

@AlexanderCska El primero -newerno se niega, el segundo sí. "Buscar archivos que son más nuevos startpero no más nuevos que stop".
Gilles 'SO- deja de ser malvado'

Ok negación funciona en el comando después. ¿Qué pasaría si no hubiera negación?
Alexander Cska

@AlexanderCska Entonces obtendrías los archivos que son más nuevos que ambos starty stop.
Gilles 'SO- deja de ser malvado'

35

Usando la solución de Gilles y después de leer man find (1) nuevamente, encontré una solución más simple. La mejor opción es -newerXY. Se pueden usar las banderas myt.

m   The modification time of the file reference
t   reference is interpreted directly as a time

Entonces la solución es

find . -type f -newermt 20111222 \! -newermt 20111225

El límite inferior en inclusivo, y el límite superior es exclusivo, ¡así que le agregué 1 día! Y es recursivo. Funciona bien en find v4.5.9.


Buen truco, gracias! Eso me ayudó a encontrar un archivo reciente que contenga una determinada palabra clave en un directorio con miles de archivos: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= buscar en las primeras 50 líneas).
Rob W

@RobW: En realidad se puede prescindir de la tubería y xargs utilizando -exec ... +en find(1), como: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Esto hace lo mismo, pero más barato.
Verdadero

Tuve que incluir las marcas de tiempo con comillas dobles (estoy en Ubuntu Xenial con find 4.7.0-git).
IsaacS

13

Además de las respuestas ya dadas, tenga en cuenta que puede especificar directamente sus fechas:

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

o

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

si además desea especificar la hora.


6

Suponiendo que no necesita precisión en los segundos, esto debería funcionar.

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

EDIT: Cambiado cmina mmindespués del comentario de @ Eelvex. EDITAR: '\!' desaparecido


hm no parece funcionar. ¿estás seguro de que recorre recursivamente los subdirectorios?
abrazadera el

Sí, funciona en mi. ¿Realmente tienes archivos modificados en ese rango de tiempo? Pruébalo con diferentes rangos de tiempo.
onur güngör

66
-cmines "cambio de estado", -mmines "cambio de datos". Probablemente quieras-mmin
Eelvex

3

findpuede tomar una fecha y hora con formato ISO, por lo que para un servidor en UTC, por ejemplo, puede especificar un desplazamiento de una cantidad de horas desde donde se encuentre. Esto también se ocupa de tener que agregar un día ya que también está comparando el tiempo:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800

0

Tenga en cuenta que la pregunta marcada como duplicada y, por lo tanto, no puede responderla directamente, es por eso que estoy publicando aquí. Esta respuesta es para responder la pregunta "necesita mover archivos a una carpeta diferente según la fecha de creación [duplicado]"

Las respuestas son razonables, pero hubo algunas limitaciones con un comando puramente de búsqueda. Escribí este script de shell para ir a través de un directorio con tantos archivos que el sistema de archivos tenía náuseas en los metadatos que intentaban realizar un ls. Además, algunos sistemas * nix rechazarán un error de demasiados argumentos al ejecutar ls.

El comando find es muy poderoso y comencé con los métodos enumerados, pero tenía tantos años de datos en todo ese directorio que tuve que pasar todos los archivos repetidamente. Esto produce una gran cantidad de innecesarios pasados ​​sobre cada archivo. Intenté hacer una pantalla por año y ejecutar varios hallazgos, pero esto resultó en muchos errores de cada hallazgo y los archivos se perderían cuando uno de los hallazgos lo movió.

Mi script de shell mueve un archivo al directorio de destino, con un año de 4 dígitos y un mes de 2 dígitos. Se puede ampliar fácilmente a un día de 2 dígitos descomentando un par de líneas y comentando sus contrapartes. Creo que es más eficiente porque se realizaron los movimientos en una pasada de búsqueda, por lo que no se necesitan múltiples comandos de búsqueda y pases sobre el directorio.

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

Una vez guardado y ejecutado, puede llamar a este script con find como el siguiente.

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

No necesita preocuparse por configurar la opción newermt para buscar, ya que todo lo que proporciona es una sola ejecución por archivo encontrado y el script toma todas las decisiones.

Tenga en cuenta que si no selecciona -type f, moverá los directorios y eso probablemente causará problemas. También puede usar -type d si está buscando mover solo directorios. No establecer el tipo seguramente producirá un comportamiento no deseado.

Recuerda que este guión se adaptó a mis necesidades. Es posible que desee utilizar simplemente mi construcción como inspiración para un guión más adecuado para sus necesidades. ¡Gracias!

Consideraciones: La eficiencia del comando puede mejorarse GRANDEMENTE permitiendo que pase un número ilimitado de argumentos a través del script. En realidad, esto es relativamente fácil si pasa la variable $ @. Ampliar la funcionalidad de esto nos permitiría usar la función find -exec + o aprovechar xargs, por ejemplo. Puedo implementarlo rápidamente y mejorar mi propia respuesta, pero este es un comienzo.

Dado que esta fue una sesión de script de una sola vez, probablemente hay muchas mejoras que se pueden hacer. ¡Buena suerte!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.