Вы на самом деле не зацикливаетесь, вы вызываете cat
только один раз для строки ./*.txt
, т. Е. Ваш сценарий эквивалентен
cat ./*.txt | grep 'banana'
Это , а не эквивалентно
grep 'banana' ./*.txt
, хотя, поскольку выходные данные для последнего префикса имени файла для каждого соответствия; вы можете использовать
grep -h 'banana' ./*.txt
для подавления имен файлов.
Проблема, с которой вы можете столкнуться, состоит в том, что ./*.txt
расширяется до значения, которое превышает максимально допустимую длину командной строки; чтобы предотвратить это, вы могли бы сделать что-то вроде
printf '%s\0' ./*.txt | xargs -0 grep -h 'banana'
, сохраняющее как файлы, содержащие пробелы, так и метасимволы оболочки и вызовы grep
как можно меньше раз 1 .
Это можно даже распараллелить; чтобы запустить 4 grep
процессов параллельно, каждый из которых обрабатывает 5 файлов одновременно:
printf '%s\0' ./*.txt | xargs -0 -L 5 -P 4 grep -h 'banana'
Я думаю, что вы намеревались запустить это:
for file in ./*.txt; do
cat "$file" | grep "banana"
done
, который будет вызывать cat
/ grep
один раз для каждого файла.
1 Сначала я подумал, что printf
также столкнется с проблемами с ограничениями длины командной строки, но похоже, что в качестве встроенной оболочки он освобожден:
$ touch '%s\0' {1000000..10000000} > /dev/null
-bash: /usr/bin/touch: Argument list too long
$ printf '%s\0' {1000000..10000000} > /dev/null
$