Tubo più file (gz) in programma in C
Domanda
Ho scritto un programma in C che funziona quando il tubo di dati nel mio programma utilizzando stdin come:
gunzip -c IN.gz|./a.out
Se voglio eseguire il mio programma su un elenco di file che posso fare qualcosa di simile:
for i `cat list.txt`
do
gunzip -c $i |./a.out
done
Ma questo farà partire il mio programma 'numero di file' volte.Mi interessa di tubazioni tutti i file nello stesso processo di esecuzione.
Come fare
for i `cat list.txt`
do
gunzip -c $i >>tmp
done
cat tmp |./a.out
Come posso fare questo?
Soluzione
Non c'è bisogno di una shell loop:
gzip -cd $(<list.txt) | ./a.out
Con il '-cd
'opzione, gzip verrà decomprimere un elenco di file di output standard (o si può usare 'gunzip -c
').Il $(<file)
la notazione espande il contenuto del file con un nome come un elenco di argomenti, senza il lancio di un sotto-processo.È equivalente a $(cat list.txt)
altrimenti.
Tuttavia, se si sente è necessario utilizzare un ciclo, quindi semplicemente il tubo di uscita dal loop in una singola istanza del programma:
for i in `cat list.txt`
do
gunzip -c $i
done |
./a.out
Se il contenuto del ciclo sono più complesse (che semplicemente gunzipping un unico file), questa potrebbe essere necessario.È inoltre possibile utilizzare '{ ... }
'I/O di reindirizzamento:
{
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done
} |
./a.out
O:
{
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done; } |
./a.out
Notare il punto e virgola;è necessario con le parentesi graffe.In questo esempio, è essenzialmente lo stesso come l'utilizzo di un formale sub-shell con le parentesi:
(
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done
) |
./a.out
O:
( cat /etc/passwd /etc/group
for i in `cat list.txt`
do
gunzip -c $i
done) |
./a.out
Nota l'assenza di un punto e virgola qui;non è più necessaria.La shell è meravigliosamente subdola in occasione.Le parentesi graffe reindirizzamento I/O può essere utile quando si ha bisogno di comandi di gruppo dopo il simbolo di pipe:
some_command arg1 arg2 |
{
first sub-command
second command
for i in $some_list
do
...something with $i...
done
} >$outfile 2>$errfile
Altri suggerimenti
Si dovrebbe essere in grado ottenere un processo gunzip
decomprimere file multipli.
zcat $(cat list.txt) | ./a.out
(zcat
è un altro modo di chiamare gunzip -c
su molti sistemi e mostra il parallelo con cat
;., Ma verificare la presenza di gzcat
se zcat
del sistema è in realtà uncompress
)
In alternativa è possibile utilizzare una shell secondaria.
(
for i in $(cat list.txt)
do
gunzip -c "$i"
done
) | ./a.out
Questa è piuttosto una domanda shell. Ma per quanto ne so si può fare:
cat file* | your_program
o
for i in file*; do gunzip -c $i; done | your_program
xargs è tuo amico
% cat list.txt | xargs gunzip -c | ./a.out
se i file nella list.txt hanno spazi tra loro, allora avete bisogno di passare attraverso alcuni cerchi in più.
Se il programma non ha bisogno di sapere quando un particolare ingresso finisce e inizia un altro, si può fare questo:
for i `cat list.txt`
do
gunzip -c $i
done |./a.out
Spero che vi aiuterà Saluti