poner miles de archivos, en carpetas con nombres determinados

poner miles de archivos, en carpetas con nombres determinados

Tengo una carpeta, llamada prueba, que solo contiene archivos jpeg. Miles de archivos. Necesito colocar estos miles de archivos, llamados 1.jpg, 2.jpg... 345623.jpg, en subcarpetas que tendrán un nombre como 001000, 002000, cada una con 1000 archivos. Por lo tanto, necesito mover todos los archivos jpg de la carpeta de prueba a subcarpetas que contengan cada uno 1000 archivos jpg, de la forma más eficiente y con mayor rendimiento.

Lo que tengo hasta ahora es:

i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n1000)

Respuesta1

find . -type f \
| split -l 1000 -a 3 --numeric-suffixes=1 \
  --filter='target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"' \
  - ''

Explicación:

  • find . -type fbusca archivos (también en subdirectorios, pero creo que en su caso todavía no hay subdirectorios).
  • split -l 1000 -a 3 --numeric-suffixes=1 ... - ''lee desde su entrada estándar ( -) y divide los datos en fragmentos, cada fragmento tiene 1000 líneas de largo ( -l 1000). Para cada fragmento se asocia un "nombre" que consiste en el prefijo vacío ( '') y el sufijo numérico que comienza en 1 ( --numeric-suffixes=1) de la longitud 3 ( -a 3). En efecto, en este punto los nombres son 001, 002y así sucesivamente.
  • --filter=...ejecuta el comando especificado por separado para cada fragmento, el nombre respectivo está disponible como $FILE. El comando a ejecutar es

    target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"
    
    • target="${FILE}000"convierte el nombre como 001o 002al futuro nombre del directorio que desee ( 001000o, 002000etc.) y lo almacena en la targetvariable.
    • mkdir "$target"crea un nuevo directorio con el nombre deseado.
    • xargs -d "\n" ...lee el fragmento completo (1000 rutas de archivos, o menos en el último fragmento) y usa cada línea completa (nueva línea como delimitador -d "\n":) como argumento para el comando que sigue.
      • mv -t "$target"mueve objetos (pasados ​​por xargs) al directorio recién creado.

Notas:

  • Al comando no le importan los nombres de los archivos. 345623.jpgno necesariamente terminará en 346000/. Posibles razones:
    • findno ordena; pero incluso si pones sort -nentre findy split, puede ser...
    • hay lagunas en la numeración. splittomará 1000 entradas, pase lo que pase (a menos que sea el último fragmento; si es así, entonces 1000 o menos).
  • mkdir ... && xargs ...no se ejecutará xargssi mkdirfalla (tenga cuidado con los directorios existentes).
  • Úselo cp -l -t "$target"en lugar de mv -t "$target"para crear vínculos físicos en directorios, dejando intactas las entradas ya existentes en el directorio actual. De esta manera, en caso de que algo salga mal, simplemente rm -rlos directorios y empezar de nuevo. Con mv, si la tarea se interrumpe, terminará con algunos archivos movidos, otros no; esto puede ser un desastre.
  • Creo que -a 3no te permitirá pasar 999( 999000después de agregar ceros al final). Si splitnecesita crear más fragmentos, fallará en medio de su trabajo. Por este motivo, asegúrese de 999que sea suficiente antes de ejecutar el comando.
  • Los nombres con nuevas líneas romperán el código (en general, los nombres de sus archivos se ven bien).

información relacionada