Embora você possa fazer isso com um script de shell, isso é difícil. Os scripts do shell não são muito bons em manipular vários trabalhos em segundo plano.
Minha recomendação é usar o make do GNU ou alguma outra versão do make que tenha um -j
opção para executar vários trabalhos em paralelo. Escreva cada subtarefa como uma regra de makefile.
Acho que o snippet do makefile abaixo implementa suas regras, mas seu código era difícil de ser seguido, então talvez eu tenha acertado. A primeira linha enumera os arquivos de saída dos arquivos de entrada (nota: nunca sobrescreva nenhum arquivo de entrada! Se o trabalho parar no meio por qualquer motivo, você terminará com dados para os quais você não saberá se ele foi processado) . As linhas recuadas são os comandos a serem executados. Use uma aba para recuar cada comando, não 8 espaços. Nesses comandos, $<
representa o arquivo de origem (um arquivo .in
), $@
representa o destino (o arquivo .out
) e $*
é o destino sem sua extensão. Todos os sinais $
nos comandos shell devem ser duplicados, e cada linha de comando é executada em um subshell separado, a menos que você coloque um \
no final que cancela essa nova linha (assim, o shell vê uma linha longa começando com set -e
e terminando com done
).
all: $(patsubst %.in,%.out,$(wildcard foo/*.in))
%.out: %.in
cp $< $*.tmp.in
set -e; \
for f in bar/*; do \
awk 'NR==FNR{a[$$0]=$$0;next}!a[$$0]' $$f $*.tmp.in >$*.tmp.out; \
mv $*.tmp.out $*.tmp.in; \
done
mv $*.tmp.in $@
Coloque isso em um arquivo chamado Makefile
e chame make -j12
.