Cómo mover los archivos según el año

14

Necesito mover archivos en función de un año. Usé el findcomando

find /media/WD/backup/osool/olddata/ -mtime +470 -exec ls -lrth {} \;|sort -k6

pero para que este comando se ejecute con éxito, necesito saber exactamente mtime470 ahora es solo una suposición. Significa que si puedo dar el año 2012, me da archivos solo relacionados con 2012.

Así que necesito consejos sobre cómo

Busque archivos basados ​​en el año, por ejemplo, 2012 y muévalos a otro directorio.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 
OmiPenguin
fuente
¿Tiene sentido usar en -exec ls ... \;lugar de -exec ... +? ¿Tu hallazgo es demasiado viejo para eso? En ese caso find ... -print0 | xargs -0 ls...sería mucho más rápido.
Hauke ​​Laging
Deseo que estas preguntas (y respuestas) que tratan con coreutils especifiquen rutinariamente si estamos tratando con utilidades GNU o BSD (u otras).
laberinto

Respuestas:

37

Desea usar la -newermtopción para find:

find /media/WD/backup/osool/olddata/ -newermt 20120101 -not -newermt 20130101

para obtener todos los archivos con tiempo de modificación en 2012.

Si su búsqueda no es compatible -newermt, también puede hacer lo siguiente para evitar el uso de cálculos de desplazamiento:

touch -d 20120101 /var/tmp/2012.ref
touch -d 20130101 /var/tmp/2013.ref
find /media/WD/backup/osool/olddata/ -newer /var/tmp/2012.ref -not -newer /var/tmp/2013.ref
Anthon
fuente
1
-newermt flag no está disponible en el comando Buscar
OmiPenguin
¿Esa debe ser una versión antigua de encontrar con la que viene tu RHEL? Proporcionaré una alternativa en la respuesta para eso
Anthon el
Sí, este es 5.2
OmiPenguin
Supongo que es la revisión de RHEL, no de find(he encontrado la versión 4.4.2)
Anthon
1
El modificador newermt no apareció en find hasta versiones posteriores a v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html .
slm
5
touch --date=2011-12-31T23:59:59 start
touch --date=2012-12-31T23:59:59 stop
find / -newer start \! -newer stop -printf %Tx" "%p\\n

-exec ls No tiene ningún sentido.

Hauke ​​Laging
fuente
1
-exec ls -ltiene más sentido e incluso más durante las pruebas.
un CVn
@ MichaelKjörling findpuede imprimir todo lo que lspueda. OK, con una excepción: escapar / citar caracteres desagradables. Pero, en general, la salida de findse puede ordenar directamente. Las llamadas inútiles de ls no hacen que todo sea más rápido.
Hauke ​​Laging
Muy a menudo uso algo bastante similar (aunque personalmente prefiero -printo posiblemente -ls ) durante las pruebas. La ventaja de usar -exec ls {}es que ya ejecuta algo externo para encontrar . Entonces, para cuando cambies de lsa mv, los cambios reales son mínimos.
un CVn
3

Según la página de manual, el argumento para -mtime es la cantidad de días que está buscando. Puede usar date +%jpara encontrar la cantidad de días desde el 1 de enero del año en curso.

Bratchley
fuente
2
Buena manera. Para ser muy "quisquilloso": -mtime -1: es cualquier archivo en las últimas 24 horas. No solo los archivos de ayer (o de hoy). Por lo tanto, también habrá una pequeña "superposición": si determina que han pasado 120 días desde 2012 y hoy son las 15:45 cuando inicia el script, terminará seleccionando archivos hasta el 31 de diciembre a las 15:45 ( y no los últimos de ese día) ... Probablemente puedas usar: nb_day - 1, y luego "eliminar" a los pocos que datan de 2013 (podrían ser encontrados por un ls -l | grep -v, PERO la salida difiere si solo tienen 1 día de edad ... muchas trampas ...)
Olivier Dulac
Desea utilizar la -daystartopción si va a trabajar con -mtime. De lo contrario, tendrá problemas con los archivos al comienzo y al final del año, sin importar cómo lo haga, a menos que lo ejecute exactamente a medianoche. Puede hacer el desplazamiento con mayor precisión -mminque con -mtimesi puede encontrar el número de minutos desde el año nuevo fácilmente. Pero existe el mismo problema con eso que con -mtime, solo por menos archivos (esos un minuto alrededor de la medianoche del año nuevo).
Anthon
1
Sí, volviendo a leer la página del manual, veo cómo se divide en horas, por lo que hacer un simple find -mtime $("date -+%j")probablemente no le dará al OP lo que está buscando. Sin embargo, lo dejo para la posteridad, ya que esto parece un posible punto ciego para que la gente caiga.
Bratchley
2

Puede intentar usar una combinación con los comandos staty / o datecomo en las siguientes frases:

BSD / Mac OS X:

find . -type f -print | while read file; do eval `stat -s "$file"`; year=`date -jf "%s" "+%Y" "$st_mtime"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Linux:

find . -type f -print | while read file; do year=`date -r "$file" "+%Y"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

En ambos casos, el enfoque es utilizar el datecomando para extraer el año desde la última hora de modificación de cada archivo y luego construir una ruta con este año. El comando mkdir -pcreará esta ruta si aún no existe. Por supuesto, puede usar algunas otras findopciones para refinar su búsqueda.

Dios de madera
fuente
1

Si hace esto desde el directorio de trabajo, puede hacerlo en su lugar:

ls -l |awk '{ if ($8 == "2013") print $9 }'

Esto simplifica las cosas considerablemente y no causa ninguna superposición. Pero también supone que estos archivos tienen más de 6 meses de antigüedad, y eso lsimprimirá el año en lugar de la hora exacta.

Para archivos de más de 6 meses de antigüedad, solo tendrá que reemplazarlo con esto:

ls -l |awk '{ if ($6 == "May") print $9 }' 

o algo similar, dependiendo del mes. Si desea crear una lista de meses para mover archivos (o si desea crear una lista por años), haga esto:

month="May Jun Jul"; 
for i in `echo $month`; 
do 
    for j in `ls -l |awk '{ if ($6 == "'$i'") print $9}'`
    do
        mkdir -p $i
        mv $j $i
    done
done
Ernie
fuente