Mover los archivos y preguntar al usuario cuando hay nombres duplicados:
Como muestran las respuestas de Subv3rsion y Eric Leschinski , el -newermt
predicado 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 a
destdir
...Tu puedes correr:
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;
En una -exec
expresión, find pasa el nombre del archivo encontrado en lugar de {}
. ;
significa -exec
que se han proporcionado el comando que se ejecutará y sus argumentos (en caso de que se pasen expresiones posteriores para encontrar después de -exec
los 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 find
comando, trabajando igual que una nueva línea. Aunque este find
comando no tiene nada después de esta -exec
expresió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 -exec
y 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 -print
antes -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
srcdir
ya se ha movido durante la misma find
operación, o
- (menos probable) se creó un archivo con el mismo nombre en algún lugar
srcdir
durante la misma find
operación, después de que se movió el original, pero lo suficientemente pronto como para encontrarlo una vez que find
atraviesa 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/
mv
mv
- Si no desea ni siquiera ese grado de interactividad y
mv
siempre 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
.
mv
acepta las banderas -b
y --backup
para 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 mv
detalles 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 -n
y desea saber qué archivos no se movieron porque había otro archivo con el mismo nombre, la mejor manera es probablemente ejecutar el find
comando original nuevamente, sin -exec
y 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 touch
y 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 -n
no 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 find
ejecuta, 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 mv
no 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 find
o 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 find
comando?
find
Los predicados pueden ser pruebas (like -type
y -newermt
), utilizadas para sus valores de retorno, o acciones (like -print
y -exec
), que a menudo se utilizan para sus efectos secundarios.
Cuando no se proporciona ningún operador (como -a
for and , -o
for or ) entre expresiones, -a
está implícito. find
emplea 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 q
p -a q
find
-type f
Al igual que las pruebas, las acciones también se evalúan como verdaderas o falsas. De esta manera, -exec
informa si el comando ejecutado salió del informe de éxito (verdadero) o error (falso). Tenemos esta cadena de -exec
expresiones 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 mv
informa 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 find
en 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 find
evalúa la siguiente -exec
expresión, que imprime el mensaje de advertencia.
Otras lecturas