¿Cuál es la forma más eficiente de mover una gran cantidad de archivos que residen en un solo directorio?

11

CentOS 5.x

Pido disculpas si esta es una pregunta repetida. He visto muchas preguntas similares (con respecto a la eliminación de archivos) pero no exactamente el mismo escenario.

Tengo un directorio que contiene cientos de miles de archivos (posiblemente más de un millón) y como solución a corto plazo a un problema diferente, necesito mover estos archivos a otra ubicación.

Para fines de discusión, digamos que estos archivos residen originalmente /home/foo/bulk/y quiero moverlos a/home/foo2/bulk2/

Si lo intento mv /home/foo/bulk/* /home/foo2/bulk2/ me sale un error de "demasiados argumentos".

El Sr. Google me dice que una alternativa para eliminar archivos en masa sería ejecutar find. Algo como: find . -name "*.pdf" -maxdepth 1 -print0 | xargs -0 rm

Eso estaría bien si estuviera borrando cosas, pero en este caso quiero mover los archivos ... Si escribo algo como find . -name "*" -maxdepth 1 -print0 | xargs -0 mv /home/foo2/bulk2/bash se queja de que el archivo no es un directorio.

¿Cuál es el mejor comando para usar aquí para mover los archivos en masa de un directorio a otro?

Mike B
fuente

Respuestas:

16

Aprovechando mvla -topción de GNU para especificar el directorio de destino, en lugar de confiar en el último argumento:

find . -name "*" -maxdepth 1 -exec mv -t /home/foo2/bulk2 {} +

Si estaba en un sistema sin la opción, podría usar un shell intermedio para obtener los argumentos en el orden correcto ( find … -exec … +no admite colocar argumentos adicionales después de la lista de archivos).

find . -name "*" -maxdepth 1 -exec sh -c 'mv "$@" "$0"' /home/foo2/bulk2 {} +
Gilles 'SO- deja de ser malvado'
fuente
Puede usar find ... -exec sh -c 'blah "$ @" blah' sh {} + "(el" truco de shell ") para tratar los problemas relacionados con el orden de los argumentos. Hay varios ejemplos de esto en findutils ( info) documentación; busque "sh -c".
James Youngman
5

Considere mvla posibilidad de utilizar el directorio principal en lugar de los archivos:

mv /home/foo/bulk /home/foo2/bulk2 && mkdir /home/foo/bulk

(Pero puede causar problemas si /home/foo/bulkdebe existir en todo momento).

Scott
fuente
1
Agregaría a eso, en caso de que su directorio de destino exista, mueva los archivos en el directorio de destino a su directorio de origen (el grande) y cambie el nombre del directorio.
sbenitezb
Gracias, gran sugerencia. En este caso, el directorio debe existir en todo momento. Gran idea sin embargo.
Mike B
Tengo que admitir que no entiendo lo que hace esta respuesta. ¿Por qué mkdir? ¿Y qué hay de ese directorio 'existente en todo momento' o no? ¿Por qué esto aceleraría las cosas?
Monica Heddneck
Sé que este comentario tiene un año, pero el último tenía cinco años, así que pensé que bien podría responder ... Sus dos primeras preguntas están correlacionadas. Esto mkdirse debe a que toda la carpeta y todo lo que contiene se movería al otro directorio y ya no existiría en el directorio anterior. Asegura que el directorio antiguo aún exista. Sin embargo, esto no sería suficiente si hubiera un servicio en ejecución constante que dependiera del primer directorio siempre existente, porque se mueve y luego se recrea. No hace nada más rápido, simplemente simplifica proporcionando menos argumentos.
Lucas Leblanc
0

Solo por variedad, me gusta usar cpio en algunos casos como este.

find tmp |cpio -v  -p --make-directories --sparse tmp2
Arthur Ulfeldt
fuente
1
Si el origen y el destino están en el mismo sistema de archivos, este enfoque podría ser muy ineficiente (copia innecesaria). Además, siempre es mejor usar -print0y -0opciones.
Pabouk
0

Con GNU mv:

find . -mindepth 1 -exec mv -t /tmp {} +

En sistemas como OS X que no tienen mv -tpero tienen -print0y xargs -0:

find . -mindepth 1 -print0|xargs -0 -I, mv , /tmp

O si los nombres de archivo no contienen espacios, comillas, barras diagonales inversas o líneas nuevas (con OS X xargs) o comillas, barras diagonales inversas o líneas nuevas (con GNU xargs):

ls|xargs -I, mv , /tmp
Lri
fuente
-3

Por un tiempo específico intente lo siguiente:

find . -name "*" -type f -mtime +7 -exec mv -t /folder/to/transfer/files {} +
vaquero
fuente