Quero executar um comando N vezes em paralelo usando bash e xargs em um sistema Linux. O comando é:
for i in `seq 1 $(howmany.txt)`; do aprogramm --file file$i.dat ; done
O arquivo howmany.txt
contém o valor 100
e ntimes.txt
contém o valor 5
.
Os arquivos file1
existem file100
, em sequência de 1 a 100, e eu quero processá-los 5 de cada vez em paralelo. Como faço isso com xargs
?
Há alguns problemas com o que você mostra. Primeiro,
$(howmany.txt)
tentará executarhowmany.txt
. Se for um script executável, armazenado em seu PATH, que imprime um número, então pode funcionar, mas se for apenas um arquivo de texto com um número, você vai querer$(cat howmany.txt)
. Segundo, é melhor (mais claro e permite comandos aninhados) usar$( command )
em vez de`seq`
command.Dito isto, para fazer isso com
xargs
, você vai querer algo como:Mas, na verdade, esse é um trabalho para o GNU parallel :
Ou, se todos os seus arquivos forem nomeados
fileN
e você quiser processar todosfileN
(então você realmente não precisa dohowmany.txt
), então você pode fazer:Uma das muitas vantagens
parallel
éxargs
que você pode alterar o númerohowmany.txt
enquanto ele estiver em execução, para poder aumentar ou diminuir o número de trabalhos em execução.Em vez de escrever um script para executar os comandos, escreva um script que ecoe os comandos:
Cada linha dessa saída deve ser uma sintaxe de comando válida para qualquer shell que você usar.
Quando a saída estiver boa, canalize-a para parallel(1) com a
-j5
opção de executar 5 tarefas em paralelo:Para processar os arquivos em lotes, use
xargs -n
. Se um único arquivo for processado por lote, use 1:Para processá-los em paralelo, use
-P
.Suposições:
howmany.txt
entimes.txt
são garantidos para conter um único inteiro e nada maisfind . -name 'file*.dat'
pode retornar mais arquivos do que o desejado)Para fins de demonstração:
Uma ideia usando o método de Jim para imprimir uma lista de nomes de arquivos canalizados para xargs`:
Isso gera:
Recentemente tive que resolver isso sem usar xargs/parallel....