Convertendo vários arquivos usando programas que aceitam stdin e output para stdout

0

Eu quero converter uma lista de arquivos em um diretório para outro diretório usando alguns programas de pré-processamento.

Eu sei que posso fazer isso por um arquivo:

cat "$INDIR/$file" | ./program > "$OUTDIR/$file"

E sei que posso fazer isso para vários arquivos:

for file in $(ls -1 $INDIR); do
    cat "$INDIR/$file" | ./program > "$OUTDIR/$file";
done

Mas o problema é que o ./program requer algum tempo para inicializar, e eu não quero que a sobrecarga seja repetida, já que haverá muitos arquivos dentro de $INDIR , e minha abordagem acima será sempre reinicie o ./program para cada arquivo no diretório. Isso é lento.

Então, minha pergunta é: Existe uma maneira de fazer minha tarefa acima sem reinicializar o ./program , no bash?

(edit after @grawity) Entendendo que não podemos simplesmente alimentar todos os arquivos de uma só vez para o stdin de ./program para poder separar a saída, estou esperando poder ter uma função create_into_pipeline que faz algo assim:

process_pipeline = create_into_pipeline(./program.pl | ./program.py | ./program.bash | ./program);
for file in $(ls -1 $INDIR); do
    process_pipeline < cat "$INDIR/$file" > "$OUTDIR/$file.new";
done

Se não for possível, então eu acho que vou criar um script Python que funcionará como um servidor web e chamando ./program conforme apropriado. Mas eu quero saber se posso fazer isso no bash, já que acredito que será mais eficiente em termos de tempo no bash do que no Python (você também pode provar que esse ponto está errado e eu vou em frente com o Python).

Mais alguns detalhes

O ./program é, na verdade, uma sequência de programas conectados uns aos outros, como tal:

./program.pl | ./program.py | ./program.bash | ./program

Eu considerei cada programa para usar a opção para processar um diretório de arquivos e saída para outro diretório, preservando os nomes dos arquivos. Mas como tenho quatro programas lá, não quero criar três diretórios temporários, pois o acesso ao disco rígido será lento. Então, eu não quero isso:

./program.pl $INDIR $OUTDIR;
./program.py $INDIR $OUTDIR;
./program.bash $INDIR $OUTDIR;
./program $INDIR $OUTDIR;

Apenas uma informação adicional no caso de poder alterar a resposta (e, na verdade, o último programa ./program não tem essa opção para processar um diretório, então eu não posso ir com essa abordagem de qualquer maneira).

    
por justhalf 09.06.2014 / 05:37

1 resposta

2

Não, não é possível - pelo menos não sem reescrever os temas dos programas.

Atualmente, cada um dos seus programas espera exatamente um arquivo em seu stdin. Algumas ou outras partes de sua inicialização estão configurando o estado referente ao processamento desse arquivo único. Eles executam essa inicialização e, em seguida, continuam lendo de stdin até atingirem "end of file" e, em seguida, sair.

Existem dois problemas aqui. A primeira é que um pipe não possui nenhum outro limite além do "fim do arquivo" (quando o gravador fecha o seu final). Você teria que criar algum tipo de sincronização especial para determinar quando um arquivo termina e outro arquivo é iniciado. (Talvez pacotes consistindo de comprimento + dados, com pacotes vazios marcando o final de um arquivo.) Você também precisaria de uma versão customizada de cat que suporte isso.

O segundo problema é que alguns dos programas, eles mesmos, não esperam mais de um arquivo em seu stdin. Cada um deles teria que ser reescrito para 1) entender o esquema de sincronização para separar corretamente vários arquivos em stdin; 2) mover o processamento para um loop, para cada arquivo lido; 3) reinicialize alguma parte de sua memória antes de processar cada arquivo (isso depende muito do que exatamente cada programa faz).

Nota: Você diz que "o último programa ./program não tem essa opção para processar um diretório". Eu suponho que os outros programas do tenham essa opção. Isso significa que, para esses programas, # 2 e # 3 já estão implementados e podem ser ligados apenas ao código stdin de vários arquivos (etapa 1, que você ainda precisa implementar em todos os programas).

    
por 09.06.2014 / 07:15

Tags