¿Cómo encontrar archivos entre dos fechas usando "buscar"?


21

Tengo una cuenta de correo electrónico que ha superado los 60 GB de correos electrónicos y actualmente tengo muchos problemas para usar un cliente de correo electrónico para archivar correos electrónicos del año pasado (2011).

A través de la terminal, estoy tratando de usar find para localizar los archivos entre 2011-01-01 y 2011-12-31, pero fue en vano.

¿Cómo puedo encontrar archivos entre dos fechas?

Si es relevante, el objetivo final será un lote que moverá cada archivo encontrado, que coincida con el intervalo de fechas, a una carpeta.


@EliahKagan En ese momento, si la memoria funciona, los nombres duplicados no eran un problema. No obstante, si le informa que tiene el tiempo, siempre se agradece la información adicional sobre un tema dado :) Además, he votado su respuesta, ya que proporciona información adicional sobre este tema.
Zuul

@EliahKagan En ese caso, te animo a que proporciones una respuesta con la práctica prueba de fallas que has resaltado :)
Zuul

Respuestas:


16

Puedes usar este script:

#!/bin/bash
for i in $(find Your_Mail_Dir/ -newermt "2011-01-01" ! -newermt "2011-12-31"); do
  mv $i /moved_emails_dir/
done

66
La salida de findno debe procesarse en un forbucle de shell como este, excepto cuando se garantiza que ningún archivo tenga espacios en blanco en su nombre. -exec, -execdirO -print0 | xargspor lo general se debe utilizar en su lugar; Otra posible solución, que generalmente es mucho menos deseable pero permite forque se use un bucle, es establecer temporalmente IFSpara que un espacio no sea reconocido como un separador de campo.
Eliah Kagan

@EliahKagan, entonces, ¿cómo se vería el comando entonces: solo reemplace findcon exec? ¿Te importaría agregar una respuesta que aborde el uso de espacios .. ?? Muy apreciado.
SherylHohman

3
@ SherylHohman No, no use el execcomando. Use un findcomando con la -execacción para ejecutar mv, o lo que necesite ejecutar, como se describe en la respuesta que publiqué . Cuando find... -execejecuta su comando con los nombres de ruta que encontró, no utiliza un shell, por lo que los espacios no activan la división o el bloqueo de palabras . (Es posible que desee publicar una nueva pregunta sobre su caso específico, o preguntar exactamente lo que quiere saber).
Eliah Kagan

@EliahKagan Lo siento, leí mal tu publicación, ¡y fue tuya ! ¡Eres increíble! ¡Tu publicación es excelente ... y gracias por responder, aunque fue mi propio error al leer!
SherylHohman

40

Bash encuentra archivos entre dos fechas:

find . -type f -newermt 2010-10-07 ! -newermt 2014-10-08

Devuelve una lista de archivos que tienen marcas de tiempo después del 2010-10-07 y antes del 2014-10-08

Bash encuentra archivos desde hace 15 minutos hasta ahora:

find . -type f -mmin -15

Devuelve una lista de archivos que tienen marcas de tiempo después de hace 15 minutos pero antes de ahora.

Bash encuentra archivos entre dos marcas de tiempo:

find . -type f -newermt "2014-10-08 10:17:00" ! -newermt "2014-10-08 10:53:00"

Devuelve archivos con marcas de tiempo entre 2014-10-08 10:17:00y2014-10-08 10:53:00


10

Mover los archivos y preguntar al usuario cuando hay nombres duplicados:

Como muestran las respuestas de Subv3rsion y Eric Leschinski , el -newermtpredicado selecciona archivos modificados más recientemente que la fecha (y la hora opcional) especificada como su operando. Para buscar archivos

  • en cualquier lugar srcdir(es decir, incluidos sus subdirectorios, sus subdirectorios, etc.)
  • última modificación en (por ejemplo) septiembre de 2014
  • y moverlos adestdir

...Tu puedes correr:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;

En una -execexpresión, find pasa el nombre del archivo encontrado en lugar de {}. ;significa -execque se han proporcionado el comando que se ejecutará y sus argumentos (en caso de que se pasen expresiones posteriores para encontrar después de -execlos argumentos de ese predicado en particular , vea a continuación un ejemplo de esto). ;debe ser escapado \;para que no sea interpretado especialmente por el shell. (Sin \, ;terminaría todo el findcomando, trabajando igual que una nueva línea. Aunque este findcomando no tiene nada después de esta -execexpresión, no pasar el ;argumento sigue siendo un error de sintaxis).

Si solo desea enumerar los archivos, lo cual es aconsejable si no está seguro de cómo se almacenan los correos electrónicos antiguos o qué otros archivos pueden estar presentes, omita -execy todo a la derecha. (Para el correo electrónico, a menudo los correos electrónicos de diferentes fechas se almacenan en el mismo archivo; para alguien en la situación descrita en la pregunta aquí, recomiendo investigar cómo se almacenan antes de mover cualquier archivo). Si desea imprimir sus nombres y moverse ellos, agregue -printantes -exec.

mv -i solicita en cualquier momento que un archivo se sobrescriba en el destino, como sucedería si:

  • existe un archivo con el mismo nombre de una copia de seguridad anterior, o
  • un archivo del mismo nombre pero de un subdirectorio diferente de srcdirya se ha movido durante la misma findoperación, o
  • (menos probable) se creó un archivo con el mismo nombre en algún lugar srcdirdurante la misma findoperación, después de que se movió el original, pero lo suficientemente pronto como para encontrarlo una vez que findatraviesa un subdirectorio diferente.

Otras formas de invocar rm:

Tiene otras opciones sobre cómo manejar archivos con nombres duplicados.

  • Sin -i(es decir, ), normalmente no solicitaría aprobación, pero lo haría si el archivo de destino fuera de solo lectura. ( incluso puede sobrescribir a veces un archivo de solo lectura, como si el usuario que lo ejecuta posee el archivo).mv {} destdir/mvmv
  • Si no desea ni siquiera ese grado de interactividad y mvsiempre quiere (intentar) sobrescribir archivos con nombres idénticos, use mv -f.
  • Si, por el contrario, desea omitir los archivos de origen cuando ya hay un archivo de destino con el mismo nombre, use mv -n.
  • mvacepta las banderas -by --backuppara renombrar automáticamente los archivos con nombres idénticos que ya existen en el destino. Por defecto ~se agrega para generar el nombre de la copia de seguridad, y si ya existe un archivo con el nombre y un archivo con el nombre de la copia de seguridad en el destino, el archivo de la copia de seguridad se sobrescribe. Este valor predeterminado puede ser anulado por las opciones pasadas al invocar mv, y por las variables de entorno. Consulte los man mvdetalles y el ejemplo a continuación.

Mover los archivos y crear copias de seguridad en caso de nombres duplicados:

Para mover todos los archivos, haga una copia de seguridad de los archivos con nombres duplicados usando un ~sufijo y use sufijos numerados cuando ya existan archivos (para evitar sobrescribir cualquier cosa), ejecute:.~n~.~

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;

Si omitió archivos con nombres duplicados y desea saber cuáles:

Si usa mv -ny desea saber qué archivos no se movieron porque había otro archivo con el mismo nombre, la mejor manera es probablemente ejecutar el findcomando original nuevamente, sin -execy todo a la derecha. Esto imprimirá sus nombres.
También imprimirá los nombres de los archivos coincidentes creados desde que ejecutó el find .... -exec ...comando original , pero para esta aplicación normalmente no habrá ninguno ya que está buscando archivos con tiempos de modificación antiguos. Es posible darle a un archivo una marca de tiempo de modificación anterior a su edad real, con touchy otros mecanismos, pero no parece probable que ocurra en este caso sin su conocimiento.

Saber de inmediato que los archivos se omiten debido a nombres duplicados:

mv -nno informa, ni devuelve ningún código de salida especial , cuando se abstiene de mover un archivo. Por lo tanto, si desea que se le informe inmediatamente de los archivos omitidos mientras se findejecuta, tendrá que hacer un paso por separado para eso. Una forma es:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -n {} destdir/ \; \
    -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \; 

Algunas consideraciones técnicas probablemente menores: Esto advierte incorrectamente si mvno se puede copiar un archivo por un motivo diferente al que existe en el destino y se cierra con éxito . Parece poco probable, pero no estoy seguro de que sea imposible. También sufre potencialmente una condición de carrera : advertiría cuando no haya ningún error real, si se creara un nuevo archivo con el mismo nombre en el mismo lugar durante el poco tiempo después de que se movió el archivo anterior y antes de que se verificara A ver si fue eliminado. (Teniendo en cuenta la aplicación, dudo que algún problema ocurra alguna vez). Podría reescribirse para verificar el destino antesmover el archivo en lugar de después: entonces la condición de carrera se relacionaría con los archivos de destino recién creados en lugar de los archivos de origen. Y aunque los errores y advertencias informados por findo mv(o [, aunque no debería haber ninguno) se escribirán en error estándar , nuestra ...skipped (exists in...advertencia se escribe en la salida estándar . Normalmente, ambos aparecen en su terminal, pero esto puede ser importante si está haciendo scripts.

He dividido ese comando en dos líneas para facilitar la lectura. Se puede ejecutar de esa manera, o puede eliminar la \y la nueva línea (es decir, el salto de línea).

¿Cómo funciona ese findcomando?

findLos predicados pueden ser pruebas (like -typey -newermt), utilizadas para sus valores de retorno, o acciones (like -printy -exec), que a menudo se utilizan para sus efectos secundarios.

Cuando no se proporciona ningún operador (como -afor and , -ofor or ) entre expresiones, -aestá implícito. findemplea evaluación de cortocircuito para y y o . (es decir, ) es verdadero solo si las expresiones p y q son ambas verdaderas, por lo que no es necesario evaluar q si p es falso. Aunque a menudo no lo pensamos en estos términos, esta es la razón por la cual las pruebas tienen que ser ciertas para que se evalúen acciones o pruebas posteriores. Por ejemplo, supongamos que viene sobre un directorio. Se evalúa como falso, por lo que puede omitir todo después.p qp -a qfind-type f

Al igual que las pruebas, las acciones también se evalúan como verdaderas o falsas. De esta manera, -execinforma si el comando ejecutado salió del informe de éxito (verdadero) o error (falso). Tenemos esta cadena de -execexpresiones conectadas con implícito y :

-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;

Esto intenta mover el archivo y, si mvinforma un error, se detiene. No queremos advertir sobre un archivo omitido correctamente si algún otro problema fue por qué no se movió.

Pero si tuvo éxito, entonces ejecuta el [comando . Al igual que find, [admite su propio tipo de expresiones pasadas como argumentos. [ -f {} ]comprueba si el operando después -f(pasado a él finden lugar de {}) existe (y es un archivo normal), y devuelve verdadero / éxito o falso / fracaso.
(Los estados de salida de muchos comandos se interpretan mejor como significando éxito o fracaso, pero [el estado de existencia de los comandos generalmente se interpreta mejor como verdadero o falso).

Si se [devuelve falso, el archivo desaparece, por lo que se movió, por lo que no es necesario hacer nada. Pero si se [devuelve falso, el archivo sigue ahí. Luego findevalúa la siguiente -execexpresión, que imprime el mensaje de advertencia.

Otras lecturas


Cuando llegue el momento, espero que añadir una sección sobre consideraciones de rendimiento y -exec ... +con mv -t, en algún momento pronto.
Eliah Kagan
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.