Use paralelo para dividir muitos diretórios em subdiretórios ou paralelizar esta tarefa

Use paralelo para dividir muitos diretórios em subdiretórios ou paralelizar esta tarefa

Quero paralelizar a divisão de muitos diretórios em subdiretórios usando parallelou usando outra ferramenta ou método.

Por exemplo, eu tenho 1.000.000 de diretórios com conteúdo, mas é demais para um diretório, então quero criar 10 diretórios no diretório principal e mover em cada um deles 100.000 diretórios originais. Também quero usar a classificação por data. eu já pergunteipergunta semelhante aqui, mas não é duplicado, pois tentei novos comandos, obtive novos resultados e agora reformulei a questão.

Então, eu já tentei isso

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

e isto

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

comandos, mas ele move apenas ~ 10.000 para um subdiretório (às vezes ~ 6.200, às vezes ~ 12.500) e cria muitos subdiretórios - às vezes 10 vezes mais do que eu preciso.

Eu também tentei usar isso:

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

mas deubash: /bin/ls: Argument list too long .

Claro, não preciso exatamente de 100.000 dirs em cada subdiretório, pode ser 101.000 ou 98.500 dirs, deve ser um número na faixa de 100.000

Como posso executar esta tarefa em paralelo ou usando parallel?

Responder1

O problema é que existe um limite superior de bytes que uma linha de comando pode ocupar após a expansão do shell, esse limite depende do limite do sistema

getconf ARG_MAX

causando assim o número de argumentos pormv {} varie dependendo do comprimento do nome do arquivo de entrada sempre que você atingir o limite máximo.

Uma solução para evitar esse limite sem abrir mão do uso do paralelo é dividir a tarefa em duas etapas

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

Explicação

  • A primeira etapa usa a opção--pipe de dividir o stdin em um determinado número destdins menores, cada um contendo n linhas conforme especificado pela opção -N. Você pode observar o efeito usando este exemplo

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

    que dá uma divisão exata na marca de 100.000

    100000
    100000
    100000
    ...
    
  • No segundo estágio, os paralelos internos tomam ostdins menorescomo seu novo stdin para executar seus trabalhos, a -Xopção insere tantos argumentos quanto o comprimento da linha de comando permitir

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

Responder2

Este problema lida com IO pesado. Duvido que parallelseja realmente útil nesta situação.

De qualquer forma, sugiro que você considere uma abordagem "tradicional":

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

onde

  • ls -tr | nl classifica os diretórios por data e adiciona um número de diretório auxiliar
  • $2 !~ /^dir_/é usado para pular as pastas recém-criadas.
  • i=1+int($1/100000)calcula o número da pasta com base no número do diretório
  • print $2 | "xargs mv -t dir_"imove-se sem proliferação de processos

Se possível compare também os respectivos tempos: time ....(e partilhe connosco os resultados ☺)

informação relacionada