grep из 7 ГБ текстового файла ИЛИ много меньших - PullRequest
1 голос
/ 08 февраля 2020

У меня около двух тысяч текстовых файлов в папке.

Я хочу l oop каждый и искать конкретное c слово в строке.

for file in "./*.txt";
do
    cat $file | grep "banana"
done

Я был интересно, если бы объединить все текстовые файлы в один файл было бы быстрее.

Весь каталог имеет около 7 ГБ.

1 Ответ

2 голосов
/ 08 февраля 2020

Вы на самом деле не зацикливаетесь, вы вызываете 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
$ 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...