Я не уверен:
grep -r -i 'the brown dog' /*
действительно то, что вы имели в виду. Это будет означать рекурсивный grep во всех не скрытых файлах и директориях /
(но все же заглянуть внутрь скрытых файлов и каталогов внутри них).
Предполагая, что вы имели в виду:
grep -r -i 'the brown dog' /
Несколько вещей, на которые стоит обратить внимание:
- Не все
grep
реализации поддерживают -r
. И среди тех, кто это делает, поведение отличается: некоторые переходят по символическим ссылкам на каталоги при обходе дерева каталогов (что означает, что вы можете в конечном итоге просмотреть один и тот же файл несколько раз или даже выполнить бесконечные циклы), некоторые - нет. Некоторые будут смотреть внутри файлов устройств (и это займет довольно много времени, /dev/zero
например) или каналов или двоичных файлов ..., некоторые не будут.
- Это эффективно, так как
grep
начинает искать внутри файлов, как только обнаруживает их. Но пока он просматривает файл, он больше не ищет больше файлов для поиска (что, вероятно, также хорошо в большинстве случаев)
Твой:
find / -type f -exec grep -i 'the brown dog' {} \;
(убрал то, -r
что здесь не имело смысла) ужасно неэффективно, потому что вы запускаете по одному grep
на файл. ;
следует использовать только для команд, которые принимают только один аргумент. Более того, здесь, поскольку grep
выглядит только в одном файле, он не будет печатать имя файла, поэтому вы не будете знать, где находятся совпадения.
Вы не заглядывая внутрь файлы устройства, трубы, симлинки ..., вы не следующие ссылок, но вы по- прежнему потенциально смотрите внутри вещи , как /proc/mem
.
find / -type f -exec grep -i 'the brown dog' {} +
было бы намного лучше, потому что grep
было бы выполнено как можно меньше команд. Вы получите имя файла, если только у последнего запуска не будет только одного файла. Для этого лучше использовать:
find / -type f -exec grep -i 'the brown dog' /dev/null {} +
или с GNU grep
:
find / -type f -exec grep -Hi 'the brown dog' {} +
Обратите внимание, что grep
он не будет запущен, пока find
не найдет достаточно файлов для его пережевывания, поэтому будет некоторая начальная задержка. И find
не будет продолжать поиск других файлов, пока grep
не вернется предыдущий . Распределение и передача большого списка файлов оказывает некоторое (вероятно, незначительное) влияние, поэтому в целом он, вероятно, будет менее эффективным, чем grep -r
тот, который не следует по символической ссылке или не заглядывает внутрь устройств.
С инструментами GNU:
find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'
Как и выше, grep
будет запущено как можно меньше экземпляров, но find
будет продолжаться поиск большего количества файлов, пока первый grep
вызов просматривает первый пакет. Это может или не может быть преимуществом, хотя. Например, данные, хранящиеся на вращающихся жестких дисках, find
и grep
доступ к данным, хранящимся в разных местах на диске, замедляют пропускную способность диска, вызывая постоянное перемещение головки диска. В настройке RAID (где find
и grep
могут иметься доступ к разным дискам) или на SSD это может иметь положительное значение.
В настройке RAID выполнение нескольких одновременных grep
вызовов также может улучшить ситуацию. Все еще с инструментами GNU на хранилище RAID1 с 3 дисками,
find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'
может значительно увеличить производительность. Однако обратите внимание, что вторая grep
будет запущена только после того, как будет найдено достаточно файлов для заполнения первой grep
команды. Вы можете добавить -n
опцию xargs
для того, чтобы это произошло раньше (и передавать меньше файлов за grep
вызов).
Также обратите внимание, что если вы перенаправляете xargs
вывод на что-либо, кроме оконечного устройства, то greps
s начнут буферизовать свои выходные данные, что означает, что выходные данные этих grep
s будут, вероятно, неправильно чередоваться. Вам придется использовать stdbuf -oL
(там, где это доступно, например, в GNU или FreeBSD) их, чтобы обойти это (у вас все еще могут быть проблемы с очень длинными строками (обычно> 4 КБ)) или каждый из них записывает свои выходные данные в отдельный файл и объединяет их все в итоге.
Здесь искомая строка является фиксированной (не является регулярным выражением), поэтому использование -F
опции может иметь значение (маловероятно, поскольку grep
реализации уже знают, как ее оптимизировать).
Еще одна вещь, которая может иметь большое значение, это исправить языковой стандарт на C, если вы находитесь в многобайтовом языковом стандарте:
find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'
Чтобы не заглядывать внутрь /proc
, /sys
... используйте -xdev
и укажите файловые системы, в которых вы хотите искать:
LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +
Или удалите пути, которые вы хотите явно исключить:
LC_ALL=C find / \( -path /dev -o -path /proc -o -path /sys \) -prune -o \
-type f -exec grep -i 'the brown dog' /dev/null {} +