Передача нескольких файлов (gz) в программу C

Я написал C-программу, которая работает, когда я передаю данные в свою программу, используя stdin, например:

gunzip -c IN.gz|./a.out

Если я хочу запустить свою программу в списке файлов, я могу сделать что-то вроде:

for i `cat list.txt`
do
  gunzip -c $i |./a.out
done

Но это запустит мою программу "количество файлов" раз. Я заинтересован в том, чтобы передать все файлы в один и тот же процесс.

Нравится делать

for i `cat list.txt`
do
  gunzip -c $i >>tmp
done
cat tmp |./a.out

Как я могу это сделать?

5 ответов

Решение

Там нет необходимости для цикла оболочки:

gzip -cd $(<list.txt) | ./a.out

С-cd'опция, gzip распакует список файлов на стандартный вывод (или вы можете использовать')gunzip -c"). $(<file) нотация расширяет содержимое именованного файла в виде списка аргументов без запуска подпроцесса. Это эквивалентно $(cat list.txt) иначе.

Однако, если вы чувствуете, что должны использовать цикл, просто перенаправьте вывод из цикла в один экземпляр вашей программы:

for i in `cat list.txt`
do
    gunzip -c $i
done |
./a.out

Если содержимое цикла является более сложным (чем простое копирование одного файла), это может быть необходимо. Вы также можете использовать{ ... }' I/O перенаправление:

{
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
    gunzip -c $i
done
} |
./a.out

Или же:

{
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
    gunzip -c $i
done; } |
./a.out

Обратите внимание на точку с запятой; это необходимо с брекетами. В этом примере это по сути то же самое, что и использование формальной суб-оболочки с круглыми скобками:

(
cat /etc/passwd /etc/group
for i in `cat list.txt`
do
    gunzip -c $i
done
) |
./a.out

Или же:

( cat /etc/passwd /etc/group
  for i in `cat list.txt`
  do
      gunzip -c $i
  done) |
./a.out

Обратите внимание на отсутствие точки с запятой здесь; это не нужно. Снаряд чудесно окутан иногда. Перенаправление фигурных скобок может быть полезно, когда вам нужно сгруппировать команды после символа канала:

some_command arg1 arg2 |
{
first sub-command
second command
for i in $some_list
do
    ...something with $i...
done
} >$outfile 2>$errfile

Вы должны быть в состоянии получить один gunzip Процесс распаковать несколько файлов.

zcat $(cat list.txt) | ./a.out

(zcat это еще один способ позвонить gunzip -c на многих системах и показывает параллель с cat; но проверьте gzcat если ваша система zcat на самом деле uncompress.)

В качестве альтернативы вы можете использовать вложенную оболочку.

(
  for i in $(cat list.txt)
  do
    gunzip -c "$i"
  done
) | ./a.out

Это скорее вопрос оболочки. Но AFAIK вы можете сделать:

cat file* | your_program

или же

for i in file*; do gunzip -c $i; done | your_program

Если вашей программе не нужно знать, когда заканчивается определенный ввод и начинается другой, вы можете сделать это:

for i `cat list.txt`
do
  gunzip -c $i
done |./a.out

Я надеюсь, что это поможет вам С уважением

xargs твой друг

% cat list.txt | xargs gunzip -c | ./a.out

если в файлах list.txt есть пробелы, вам нужно пройти через некоторые дополнительные операции.

Другие вопросы по тегам