Pipe vários arquivos (GZ) no programa C
Pergunta
Eu escrevi um programa C que funciona quando coloco dados no meu programa usando o stdin como:
gunzip -c IN.gz|./a.out
Se eu quiser executar meu programa em uma lista de arquivos, posso fazer algo como:
for i `cat list.txt`
do
gunzip -c $i |./a.out
done
Mas isso iniciará o número de horários dos arquivos do meu programa. Estou interessado em expor todos os arquivos para o mesmo processo executado.
Como fazer
for i `cat list.txt`
do
gunzip -c $i >>tmp
done
cat tmp |./a.out
Como posso fazer isso?
Solução
Não há necessidade de um loop de concha:
gzip -cd $(<list.txt) | ./a.out
Com o '-cd
'Opção, o GZIP descompactará uma lista de arquivos para saída padrão (ou você pode usar'gunzip -c
'). o $(<file)
A notação expande o conteúdo do arquivo nomeado como uma lista de argumentos sem iniciar um subprocesso. É equivalente a $(cat list.txt)
por outro lado.
No entanto, se você sentir que deve usar um loop, basta colocar a saída do loop em uma única instância do seu programa:
for i in `cat list.txt`
do
gunzip -c $i
done |
./a.out
Se o conteúdo do loop for mais complexo (do que simplesmente atirar um único arquivo), isso pode ser necessário. Você também pode usar '{ ... }
'Redirecionamento de E/S:
{
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done
} |
./a.out
Ou:
{
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done; } |
./a.out
Observe o Semi-Colon; é necessário com aparelho. Neste exemplo, é essencialmente o mesmo que usar uma sub-concha formal com parênteses:
(
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done
) |
./a.out
Ou:
( cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done) |
./a.out
Observe a ausência de um Semi-Colon aqui; não é necessário. A concha é maravilhosamente desonesta de vez em quando. O redirecionamento de E/S do aparelho pode ser útil quando você precisar agrupar comandos após o símbolo do tubo:
some_command arg1 arg2 |
{
first sub-command
second command
for i in $some_list
do
...something with $i...
done
} >$outfile 2>$errfile
Outras dicas
Você deve poder conseguir um gunzip
Processe descompacte vários arquivos.
zcat $(cat list.txt) | ./a.out
(zcat
é outra maneira de ligar gunzip -c
em muitos sistemas e mostra o paralelo com cat
; mas verifique gzcat
Se o seu sistema zcat
é na verdade uncompress
.)
Como alternativa, você pode usar um sub shell.
(
for i in $(cat list.txt)
do
gunzip -c "$i"
done
) | ./a.out
Esta é uma questão de concha. Mas Afaik você pode fazer:
cat file* | your_program
ou
for i in file*; do gunzip -c $i; done | your_program
Xargs é seu amigo
% Cat List.txt | XARGS Gunzip -C | ./a.out
Se os arquivos no list.txt tiverem espaços neles, você precisará passar por alguns aros extras.
Se o seu programa não precisar saber quando uma entrada específica termina e outro começa, você pode fazer isso:
for i `cat list.txt`
do
gunzip -c $i
done |./a.out
Espero que isso ajude você a cumprir