Tubes multiples fichiers (gz) dans le programme C
Question
J'ai écrit un programme C qui fonctionne quand je les données de conduite dans mon programme en utilisant stdin comme:
gunzip -c IN.gz|./a.out
Si je veux lancer mon programme sur la liste des fichiers que je peux faire quelque chose comme:
for i `cat list.txt`
do
gunzip -c $i |./a.out
done
Mais cela va commencer mon programme "nombre de fichiers de fois. Je suis intéressé par la tuyauterie tous les fichiers dans le même cycle de processus.
Comme faire
for i `cat list.txt`
do
gunzip -c $i >>tmp
done
cat tmp |./a.out
Comment puis-je faire?
La solution
Il n'y a pas besoin d'une boucle shell:
gzip -cd $(<list.txt) | ./a.out
Avec l'option « -cd
», gzip décompresse une liste de fichiers à la sortie standard (ou vous pouvez utiliser « gunzip -c
»). La notation $(<file)
élargit le contenu du fichier nommé une liste d'arguments sans lancer un sous-processus. Il est équivalent à $(cat list.txt)
autrement.
Cependant, si vous sentez que vous devez utiliser une boucle, puis conduit simplement la sortie de la boucle en une seule instance de votre programme:
for i in `cat list.txt`
do
gunzip -c $i
done |
./a.out
Si le contenu de la boucle sont plus complexes (que simplement de décompresser un seul fichier), cela pourrait être nécessaire. Vous pouvez également utiliser '{ ... }
' redirection 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
Notez le point-virgule; il est nécessaire avec des accolades. Dans cet exemple, il est essentiellement identique à l'aide d'un sous-shell formelle avec des parenthèses:
(
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
Notez l'absence d'un point-virgule ici; il est pas nécessaire. La coquille est merveilleusement sournoise à l'occasion. Les accolades redirection E / S peut être utile lorsque vous avez besoin de regrouper les commandes après le symbole de la conduite:
some_command arg1 arg2 |
{
first sub-command
second command
for i in $some_list
do
...something with $i...
done
} >$outfile 2>$errfile
Autres conseils
Vous devriez pouvoir obtenir un processus de gunzip
décompressez plusieurs fichiers.
zcat $(cat list.txt) | ./a.out
(zcat
est une autre façon d'appeler gunzip -c
sur de nombreux systèmes et montre le parallèle avec cat
;. Mais pour vérifier si votre gzcat
zcat
du système est en fait uncompress
)
Sinon, vous pouvez utiliser un shell sous.
(
for i in $(cat list.txt)
do
gunzip -c "$i"
done
) | ./a.out
Ceci est plutôt une question de la coquille. Mais vous pouvez faire autant que je sache:
cat file* | your_program
ou
for i in file*; do gunzip -c $i; done | your_program
xargs est votre ami
% cat list.txt | xargs gunzip -c | ./a.out
si les fichiers list.txt ont des espaces en eux, alors vous devez passer par des cerceaux supplémentaires.
Si votre programme n'a pas besoin de savoir quand une entrée particulière se termine et un autre commence, vous pouvez faire ceci:
for i `cat list.txt`
do
gunzip -c $i
done |./a.out
J'espère que cela vous aidera Cordialement