Shell Script: obtenga todos los archivos modificados después de <date>

136

Prefiero no hacer esto en PHP, así que espero que alguien decente en scripts de shell pueda ayudar.

Necesito un script que se ejecute a través del directorio de forma recursiva y encuentre que todos los archivos con la última fecha de modificación es mayor que alguna fecha. Luego, alquilará y comprimirá los archivos manteniendo la información de la ruta.

Jonathan Leffler
fuente
14
Buena decisión de no hacerlo en PHP.
Kredns
1
Puede usar cualquiera de los lenguajes de scripting de shell decentes, por ejemplo, python, ruby, perl sin recurrir a php.
Garrow
3
@garrow Esto sería bastante simple en PHP usando un RecursiveDirctoryIterator encapsulado en un FilterIterator.
Artefacto

Respuestas:

136

tan simple como:

find . -mtime -1 | xargs tar --no-recursion -czf myfile.tgz

donde find . -mtime -1seleccionará todos los archivos en (recursivamente) directorio actual modificado el día anterior. puedes usar fracciones, por ejemplo:

find . -mtime -1.5 | xargs tar --no-recursion -czf myfile.tgz
skrat
fuente
44
Consulte la respuesta de user104848 a continuación para saber cómo tratar con espacios en los nombres de sus archivos
Brian Henk,
8
Convertir una marca de tiempo arbitraria en una fracción de tiempo relativa no parece correcta ni particularmente conveniente. La siguiente solución usando -newermtes mucho mejor.
Bobby Jack
55
Al intentar extraer cualquier archivo con cambios en una estructura con directorios, los directorios mismos se marcan modificados y se archiva toda la carpeta. Agregar -type fsolo para seleccionar archivos. Esto mantiene la estructura de la carpeta, pero solo realiza copias de seguridad de los archivos con cambios.
Brent
1
@BrianHenk user104848 cambió su nombre, estoy bastante seguro de que te refieres que esta respuesta de (actualmente) Jason Luther aunque
icc97
44
La pregunta pide encontrar archivos en una fecha arbitraria. Esta respuesta es cómo encontrar archivos por un número arbitrario de días en el pasado. No creo que esta sea la respuesta aceptada sin agregar un paso para convertir una fecha en un día delta.
Mark
91

Si tienes GNU find, entonces hay una legión de opciones relevantes. El único inconveniente es que la interfaz para ellos es menos que estelar:

  • -mmin n (tiempo de modificación en minutos)
  • -mtime n (tiempo de modificación en días)
  • -newer file (tiempo de modificación más nuevo que el tiempo de modificación del archivo)
  • -daystart (ajuste la hora de inicio desde la hora actual hasta el inicio del día)
  • Más alternativas para el tiempo de acceso y el tiempo de "cambio" o "creación".

La parte difícil es determinar la cantidad de minutos desde un momento.

Una opción que vale la pena considerar: usar touchpara crear un archivo con la marca de tiempo de modificación requerida; luego usafind con -newer.

touch -t 200901031231.43 /tmp/wotsit
find . -newer /tmp/wotsit -print
rm -f /tmp/wotsit

Esto busca archivos más nuevos que 2009-01-03T12: 31: 43. Claramente, en un script, /tmp/wotsitsería un nombre con el PID u otro valor para hacerlo único; y habría una trappara garantizar que se elimine incluso si el usuario interrumpe, y así sucesivamente.

Jonathan Leffler
fuente
65
En su lugar, puede usar -newermt '2009-01-03T12:31:43'para evitar la necesidad de crear un archivo solo como referencia.
Michael Mior
@MichaelMior: Interesante: el 'encontrar' en MacOS X 10.7.2 admite -newermt(documentado a continuación, -newerXYya que hay varias opciones; X = m, Y = t en este caso). El hallazgo de GNU en los sistemas Linux (casi arcaicos) que uso no admite las opciones, por lo que es una llegada relativamente reciente. Gracias por el aviso.
Jonathan Leffler
Esta opción está presente en GNU find 4.4.2 que estoy usando en mi sistema.
Michael Mior
2
También tenga en cuenta que GNU find también admite tiempos relativos, es decir. -newermt '-2 weeks'.
Cybolic el
1
-newermt '2009-01-03T12:31:43'se ve increíble, pero lamentablemente parece interpretar todo en la zona horaria incorrecta: lists.gnu.org/archive/html/bug-findutils/2012-12/msg00009.html
antoine
35

Puedes hacerlo directamente con alquitrán y aún mejor:

tar -N '2014-02-01 18:00:00' -jcvf archive.tar.bz2 files

Esto le indica a tar que comprima archivos más nuevos que el 1 de enero de 2014, 18:00:00.

linux_newbie
fuente
9
Huh ... He estado usando Unix desde 1984 y nunca supe esto. Siempre hay algo que aprender.
John
Las implementaciones de tareso vienen con OS X y FreeBSD solo --newerque es la opción larga para -NGNU tar.
nisetama
Esto es increíble ... solo pude hacer que funcione con bzip, no usando -xcvf y una extensión gz ... pero no soy un experto.
phil
17

Esto funcionará para cierto número de archivos. Desea incluir "-print0" y "xargs -0" en caso de que alguna de las rutas tenga espacios. Este ejemplo busca archivos modificados en los últimos 7 días. Para encontrar los modificados antes de los últimos 7 días, use "+7".

find . -mtime -7 -print0 | xargs -0 tar -cjf /foo/archive.tar.bz2

Como advierte esta página , xargs puede hacer que el comando tar se ejecute varias veces si hay muchos argumentos, y el indicador "-c" podría causar problemas. En ese caso, querrías esto:

find . -mtime -7 -print0 | xargs -0 tar -rf /foo/archive.tar

No puede actualizar un archivo tar comprimido con tar, por lo que tendría que bzip2 o gzip en un segundo paso.

Jason Luther
fuente
1
Con respecto al segundo punto, puede usar un comando tar habilitado para gzip, como la opción -z de Gnu tar, para actualizar también los archivos comprimidos.
Suncat2000
O agregue la opción 'j' para usar bzip en
tar
3
Como dije anteriormente en la respuesta de Jonathan, esto tomará las carpetas que tienen cambios que causan la importación de todos sus archivos. Agregar -type fsolo para seleccionar archivos. Esto mantiene la estructura de la carpeta, pero solo respalda los archivos con cambios / agregados recientemente.
Brent
12

Esto debería mostrar todos los archivos modificados en los últimos 7 días.

find . -type f -mtime -7 -print

Coloca eso en alquitrán / cremallera, y deberías ser bueno.

Chris Doggett
fuente
4

Simplemente haría lo siguiente para hacer una copia de seguridad de todos los archivos nuevos de hace 7 días

tar --newer $(date -d'7 days ago' +"%d-%b") -zcf thisweek.tgz .

tenga en cuenta que también puede reemplazar 'hace 7 días' con cualquier cosa que se adapte a sus necesidades

Puede ser : date -d'yesterday' +"%d-%b"

O incluso : date -d'first Sunday last month' +"%d-%b"

Michel
fuente
3

bien debajo de Linux intente leer la página del comando find

man find

algo como esto debería

 find . -type f -mtime -7 -print -exec cat {} \; | tar cf - | gzip -9

y lo tienes

Luixv
fuente
3

Puede obtener una lista de archivos modificados por última vez hace más de x días con:

find . -mtime -x

Luego solo tiene que tar y comprimir los archivos en la lista resultante, por ejemplo:

tar czvf mytarfile.tgz `find . -mtime -30`

para todos los archivos modificados durante el mes pasado.

Mouviciel
fuente
3
"-mtime x" coincide con los archivos modificados exactamente "x" días atrás, use "-mtime -x" para hacer coincidir los archivos modificados hace menos de "x" días.
Lance Richardson
2

Este script encontrará archivos con una fecha de modificación de dos minutos antes y después de la fecha dada (y puede cambiar los valores en las condiciones según sus requisitos)

PATH_SRC="/home/celvas/Documents/Imp_Task/"
PATH_DST="/home/celvas/Downloads/zeeshan/"

cd $PATH_SRC
TODAY=$(date  -d "$(date +%F)" +%s)
TODAY_TIME=$(date -d "$(date +%T)" +%s)


for f in `ls`;
do
#       echo "File -> $f"
        MOD_DATE=$(stat -c %y "$f")
        MOD_DATE=${MOD_DATE% *}
#       echo MOD_DATE: $MOD_DATE
        MOD_DATE1=$(date -d "$MOD_DATE" +%s)
#       echo MOD_DATE: $MOD_DATE

DIFF_IN_DATE=$[ $MOD_DATE1 - $TODAY ]
DIFF_IN_DATE1=$[ $MOD_DATE1 - $TODAY_TIME ]
#echo DIFF: $DIFF_IN_DATE
#echo DIFF1: $DIFF_IN_DATE1
if [[ ($DIFF_IN_DATE -ge -120) && ($DIFF_IN_DATE1 -le 120) && (DIFF_IN_DATE1 -ge -120) ]]
then
echo File lies in Next Hour = $f
echo MOD_DATE: $MOD_DATE

#mv $PATH_SRC/$f  $PATH_DST/$f
fi
done

Por ejemplo, usted quiere tener los archivos de la fecha de modificación antes de la fecha dada solamente, usted puede cambiar 120a 0en el $DIFF_IN_DATEparámetro de desechar las condiciones del $DIFF_IN_DATE1parámetro.

Del mismo modo, si desea que los archivos tengan una fecha de modificación 1 hora antes y después de una fecha determinada, simplemente reemplácela 120por 3600in if CONDITION.

Zeeshan Ali
fuente