Mover millones de archivos a un directorio diferente con patrones de nombre específicos

10

Tengo millones de archivos con la siguiente nomenclatura en una máquina Linux:

1559704165_a1ac6f55fef555ee.jpg

Los primeros 10 dígitos son marcas de tiempo y los seguidos por un _son identificadores específicos. Quiero mover todos los archivos que coincidan con identificadores de nombre de archivo específicos a una carpeta diferente.

Intenté esto en el directorio con archivos

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

Sin embargo, recibo un error que indica:

bash 1559704165_a1ac6f55fef555ee.jpg: command not found

Cuando lo intenté, mv ??????????_a1ac*.jpg recibo una lista de argumentos de error demasiado largo. Tengo al menos 15 patrones de nombre de archivo diferentes. ¿Cómo los muevo?

Albaricoque
fuente
1
El bash lo dice todo: intenta ejecutar ese nombre de archivo ya que es el primero en la línea en la segunda etapa de la tubería (su tubería de la segunda etapa es | ??????????_a1ac*.jpg:: bash lo expande a varios nombres de archivo, el primero es 1559704165_a1ac6f55fef555ee.jpg, si termina , en esa segunda etapa de canalización, intentando ejecutar:. 1559704165_a1ac6f55fef555ee.jpg next_matching_filename 3rd_matching_filename ... nth_matching_filenameSupongo que intentaste filtrar ese nombre de archivo (ver las respuestas a continuación para eso)
Olivier Dulac

Respuestas:

15

Deberías usar:

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' \
-exec mv -t destination "{}" +

Entonces maxdepth 1significa que desea buscar en el directorio actual sin subdirectorios.

type f significa buscar solo archivos.

name '??????????_a1ac*.jpg' es un patrón que coincide con el archivo que está buscando.

mv -t destination "{}" +significa mover archivos coincidentes al destino. Aquí +agrega nuevos archivos coincidentes a los anteriores, como:

mv -t dest a b c d

Aquí abcd son diferentes archivos.

Prvt_Yadav
fuente
Gracias por responder de manera concisa la pregunta de esta persona. En lugar de simplemente descartar una solución, tal vez podría explicar cómo / qué / por qué. En lugar de ser útil para una persona, una vez, puede ser útil para todos, todo el tiempo. La misma pregunta ha sido formulada y respondida innumerables veces en los últimos 40-50 años. El problema es que nunca se explica bien. Enseñe a un hombre a pescar ... Mientras tanto: gnu.org/software/findutils/manual/html_node/find_html/… y, como suele ser el caso, Wikipedia es más útil que los documentos oficiales: en.wikipedia.org/wiki/Find_ ( Unix)
voces
Ver respuesta actualizada.
Prvt_Yadav
Tenga en cuenta que -tes una extensión GNU y, por lo tanto, puede no estar disponible en otros tipos de derivados de UNIX.
Kevin
Cuando dices "Las comillas dobles evitan la división de palabras". Supongo que te estás refiriendo "{}", en cuyo caso quiero señalar que {}el shell no expande y no necesita ser citado. El shell pasa {}a buscar, y encuentra ve {}y lo reemplaza con nombres de ruta. Find exec no utiliza el analizador de shell y no divide las palabras por sí mismo. Citarlo no hace ningún daño, es solo que la justificación dada es un poco inexacta.
jw013
@ jw013 gracias.
Prvt_Yadav
11

Tu orden

find . -maxdepth 1 -type f | ??????????_a1ac*.jpg |xargs mv -t "/home/ubuntu/ntest"

¡Canaliza la lista de todos los archivos A todos los archivos!

find . -maxdepth 1 -type f -name `*_a1ac*.jpg` -print0 |\
xargs  -0 -r mv -t "/home/ubuntu/ntest"

Hará el truco.

Waltinator
fuente
1
muchas gracias ... su solución también funcionó ... gracias por dejarme saber dónde me equivoqué
Apricot
8

Estas muy cerca. Debe usar la -nameopción para find. Y recuerda citar el patrón.

Entonces

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' |xargs mv -t "/home/ubuntu/ntest"
Stephen Harris
fuente
Muchas gracias ... su solución también funcionó ... gracias adicionales por hacerme saber que estaba cerca de la solución ... es una motivación para un novato como yo
Apricot
1
debe agregar a -print0como último argumento para encontrar (en lugar del predeterminado: -print) y agregar a -0como la primera opción para xargs (es decir:) xargs -0 mv -t "/home/ubuntu/ntest". de esa manera, se pueden manejar todo tipo de nombres de archivo extraños (con espacios en él, con "nueva línea", etc.). find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' -print0 |xargs -0 mv -t "/home/ubuntu/ntest" (Sin embargo, solo funciona con hallazgos similares a GNU)
Olivier Dulac
2

No es tan "bueno" como las findsoluciones, pero otra solución válida es hacer que los mvcomandos sean más granulares.

Esto hace 4096 movimientos, con una menor cantidad de archivos movidos por mvoperación.

FILEPAT=a1ac
for i in $(seq $((0x000)) $((0xfff))); 
do 
   H=$(printf '%x\n' $i)
   mv 1559704165_${FILEPAT}${H}*.jpg /home/ubuntu/ntest
done
RonJohn
fuente
Este es un truco inteligente para aquellos sin find(por cualquier razón).
bosque
-1

Si desea mover archivos en el mismo sistema host, lo que supongo que está haciendo con su mv, rsyncpodría ser una opción más rápida:

rsync -av --inplace -W /source/??????????_a1ac*.jpg /home/ubuntu/ntest/

--inplacey -Westán configurados para acelerar el proceso.

Si esto produce otro error de lista de argumentos demasiado largo, entonces podría alimentar listas arsync

Haga la lista con find, por ejemplo

find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txt

y dáselo a rsync

rsync -av --inplace -W --files-from=/tmp/my_image_list.txt /path/to/files /home/ubuntu/ntest/

La fuente aquí es /path/to/files, porque rsynctratará la lista que le dé como relativa a su fuente.


El punto es: rsynces más rápido que mv, si los archivos no están en el mismo sistema de archivos .

Robert Riedl
fuente
Esto es probable que golpeó la misma "lista de argumentos demasiado tiempo" error de la OP menciona
Grump
@Grump, para evitar esto, OP podría escribir la lista de archivos para copiar en un archivo, es decir, find . -maxdepth 1 -type f -name '??????????_a1ac*.jpg' > /tmp/my_image_list.txty luego pasarla a rsync --files-from=/tmp/my_image_list.txt. El punto es que rsynces más rápido. A menos que los archivos residan en el mismo sistema de archivos, que OP no ha indicado.
Robert Riedl
@RobertRiedl: debe editar su respuesta y agregar esta información. Los comentarios pueden ser impermanentes.
NickD
@ NickD, he actualizado mi respuesta.
Robert Riedl