Utilice paralelo para dividir muchos directorios en subdirectorios o paralelizar esta tarea

Utilice paralelo para dividir muchos directorios en subdirectorios o paralelizar esta tarea

Quiero paralelizar la división de muchos directorios en subdirectorios usando parallelo usando otra herramienta o método.

Por ejemplo, tengo 1.000.000 de directorios con contenido, pero es demasiado para un directorio, por lo que quiero crear 10 directorios en el directorio principal y mover en cada uno de ellos 100.000 directorios originales. También quiero utilizar la clasificación por fecha. Ya preguntépregunta similar aquí, pero esto no está duplicado, porque probé nuevos comandos, obtuve nuevos resultados y ahora reformulé la pregunta.

Entonces ya probé esto

ls -tr|parallel -n100000 mkdir "dir_{#}"\;mv {} "dir_{#}" 

y esto

ls -tr | parallel -j10 -n100000 --no-notice -k 'mkdir -p dir_{#}; mv {} -t dir_{#}' 

comandos, pero mueve solo ~ 10 000 a un subdirectorio (a veces ~ 6200, a veces ~ 12 500) y crea demasiados subdirectorios, a veces 10 veces más de lo que necesito.

También intenté usar esto:

ls -dtr * | parallel -j10 -n100000 --no-notice -k 'mkdir -p dir_{#}; mv {} -t dir_{#}'

pero dio bash: /bin/ls: Argument list too long.

Por supuesto, no necesito exactamente 100 000 directorios en cada subdirectorio, pueden ser 101 000 o 98 500 directorios, debería ser un número en el rango de 100 000.

¿Cómo puedo ejecutar esta tarea en paralelo o usando parallel?

Respuesta1

El problema es que hay un límite superior de bytes que una línea de comando puede tomar después de la expansión del shell, este límite depende del límite del sistema.

getconf ARG_MAX

lo que hace que el número de argumentos mv {}varíe dependiendo de la longitud del nombre del archivo de entrada cada vez que alcance el límite máximo.

Una solución para evitar este límite sin renunciar al uso paralelo es dividir la tarea en dos etapas.

ls -tr | parallel -N 100000 --pipe -k "mkdir dir_{#}; parallel -X mv -t dir_{#}"

Explicación

  • La primera etapa utiliza la opción --pipede dividir la entrada estándar en un número determinado deentradas estándar más pequeñas, cada uno de los cuales contiene n líneas según lo especificado por la opción -N. Puedes observar el efecto usando este ejemplo.

    seq 1000000 | parallel -N 100000 --pipe wc -l
    

    lo que da una división exacta en la marca de 100000

    100000
    100000
    100000
    ...
    
  • En la segunda etapa, los paralelos interiores toman elentradas estándar más pequeñascomo su nueva entrada estándar para ejecutar sus trabajos, la -Xopción inserta tantos argumentos como lo permita la longitud de la línea de comando

    mkdir dir_{#}; parallel -X mv -t dir_{#}
    

Respuesta2

Este problema se refiere a IO intensas. Dudo que parallelsea realmente útil en esta situación.

De todos modos te sugiero que consideres un enfoque "tradicional":

 mkdir dir_{1..10}
 ls -tr | nl | \
    awk '$2 !~ /^dir_/ {i=1+int($1/100000); print $2 | "xargs mv -t dir_"i}'

dónde

  • ls -tr | nl ordena los directorios por fecha y agrega un número de directorio auxiliar
  • $2 !~ /^dir_/se utiliza para omitir las carpetas recién creadas.
  • i=1+int($1/100000)calcula el número de la carpeta en función del número de directorio
  • print $2 | "xargs mv -t dir_"ise mueve sin proliferación de procesos

Si es posible compara también los tiempos respectivos: time ....(y comparte los resultados con nosotros ☺)

información relacionada