Tengo millones de imágenes en mi servidor de ubuntu en la nube. Cuando muevo una carpeta completa que contiene 12 millones de imágenes usando el mv
comando, sucede casi instantáneamente. Sin embargo, cuando mv
solo tomo imágenes (no la carpeta), me lleva algo de tiempo. ¿Hay alguna forma de mover todas las imágenes tan rápido como las carpetas?
Esto es lo que está sucediendo:
La carpeta src tiene 12 millones de imágenes y muevo esto a la carpeta dst usando
$ mv src ../dst
Sucede inmediatamente
Dentro de la carpeta src hago esto para mover:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
Esto lleva algo de tiempo.
¿Hay alguna manera de acelerar el segundo proceso?
dst
está en una partición mientras que../../dst
está en otra.{}
argumento donde los nombres de archivo se expandirían.find
.find ... -exec mv -t ../../dst/ {} \;
llamaríamv
una vez por archivo;find ... -exec mv -t ../../dest {} +
sería mucho más rápido, copiando tantos archivos por llamada como sea posible, pero aún no tan rápido como mover el directorio en sí como lo explica dadexix86 .Respuestas:
TL; DR : No
Para una cantidad menor de archivos, no necesitaría
find
pero, incluso en este caso simplificado y más pequeño, si solotomará más tiempo que mover todo el directorio a la vez.
¿Por qué? El punto es entender lo que
mv
hace.En pocas palabras,
mv
mueve un número (que identifica un directorio o un archivo) de un inodo (el directorio que lo contiene) a otro, y estos índices se actualizan en el diario del sistema de archivos o en el FAT (si el sistema de archivos se implementa de tal manera).Si el origen y el destino están en el mismo sistema de archivos, no hay movimiento real de datos, solo cambia la posición, el punto donde están conectados.
Entonces, cuando tiene
mv
un directorio, está haciendo esta operación una vez .Pero cuando mueve 1 millón de archivos, está haciendo esta operación 1 millón de veces .
Para darle un ejemplo práctico, tiene un árbol con muchas ramas. En particular, hay un nodo al que se unen 1 millón de ramas.
Para cortar estas ramas y moverlas a otro lugar, puede cortar cada una de ellas, de modo que haga 1 millón de cortes, o corte justo antes del nodo, haciendo así solo un corte (esta es la diferencia entre mover los archivos y El directorio).
fuente
mv
en el mismo sistema de archivos es solo una reescritura de la entrada TOC.mv *.jpg
es probable que falle para 12 millones de archivos, por eso utiliza find. La mayoría de los Unixes, incluido Linux, creo (a menos que alguien lo haya cambiado en los últimos 5-10 años) tienen una longitud máxima limitada de la línea de comando. Creo que fue 64K para Linux durante mucho tiempo. El mismo límite se aplica a las variables de entorno, estoy bastante seguro.Seguirá siendo lento porque, como se señaló, el sistema de archivos debe volver a vincular cada nombre de archivo a su nueva ubicación.
Sin embargo, puede acelerarlo de lo que tiene ahora.
Su comando find ejecuta el exec una vez para cada archivo. Entonces lanza el
mv
comando 12 millones de veces para 12 millones de archivos. Esto se puede mejorar de dos maneras.Agregue un plus al final:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
Verifique la página de manual para asegurarse de que sea compatible con su versión de
find
. El efecto debería ser ejecutar una serie demv
comandos con tantos nombres de archivos como quepan en cada línea de comando.Uso
find
yxargs
juntos.find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
El
-print0
usarán NUL, también conocido como cero bytes para separar los nombres de archivo. Esto ademásxargs -0
soluciona cualquier problemaxargs
que de otro modo tendría con espacios en los nombres de archivo. Elxargs
comando leerá la lista de nombres de archivo delfind
comando y ejecutará elmv
comando en tantos nombres de archivos como quepan.fuente
Su confusión proviene de la abstracción del sistema de archivos que le hace creer que una carpeta contiene archivos y otras carpetas en forma de árbol. Esto no es realmente cierto: todos los archivos y directorios dentro de un sistema de archivos están ubicados en el mismo nivel e identificados con números de algún tipo, dependiendo de la implementación. Los directorios son solo archivos especiales que contienen listas de otros archivos.
Cuando "mueve" archivos dentro de un sistema de archivos, los archivos reales no van a ninguna parte. Por el contrario, las listas dentro de los directorios se actualizan para reflejar el cambio.
mv src ../dst
mueve una sola entrada de lista de un directorio.
a otro../dst
, por lo que es rápido.find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
tiene que mover millones de entradas, por lo que es más lento. Potencialmente, puede acelerarse si llamamv
solo una vez y no una vez por archivo, y elmv
comando en sí puede optimizarse para mover varias entradas de directorio en un solo paso, pero no hay forma de hacerlo tan rápido como cuando mueve un solo directorio .fuente
Una respuesta simplificada
mover un archivo se realiza en 3 pasos:
Este proceso es el mismo para un archivo o una carpeta.
y obviamente hacer esto para 1 archivo es 100 más rápido que hacerlo para 100 archivos.
man link
es el add ()man unlink
es el remove ()mv
solo usa esos dos comandos anteriores y agrega un control intermedio para evitar la pérdida de datos.fuente