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 f
busca 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 son001
,002
y así sucesivamente.--filter=...
ejecuta el comando especificado por separado para cada fragmento, el nombre respectivo está disponible como$FILE
. El comando a ejecutar estarget="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"
target="${FILE}000"
convierte el nombre como001
o002
al futuro nombre del directorio que desee (001000
o,002000
etc.) y lo almacena en latarget
variable.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 porxargs
) al directorio recién creado.
Notas:
- Al comando no le importan los nombres de los archivos.
345623.jpg
no necesariamente terminará en346000/
. Posibles razones:find
no ordena; pero incluso si ponessort -n
entrefind
ysplit
, puede ser...- hay lagunas en la numeración.
split
tomará 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áxargs
simkdir
falla (tenga cuidado con los directorios existentes).- Úselo
cp -l -t "$target"
en lugar demv -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, simplementerm -r
los directorios y empezar de nuevo. Conmv
, si la tarea se interrumpe, terminará con algunos archivos movidos, otros no; esto puede ser un desastre. - Creo que
-a 3
no te permitirá pasar999
(999000
después de agregar ceros al final). Sisplit
necesita crear más fragmentos, fallará en medio de su trabajo. Por este motivo, asegúrese de999
que 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).