Что является более эффективным для определения того, какие файлы во всей файловой системе содержат строку: рекурсивный grep или поиск с помощью grep в выражении exec? Я предполагаю, что поиск будет более эффективным, потому что вы можете по крайней мере выполнить некоторую фильтрацию, если знаете расширение файла или регулярное выражение, соответствующее имени файла, но когда вы знаете только, -type f
что лучше? GNU grep 2.6.3; find (GNU findutils) 4.4.2
Пример:
grep -r -i 'the brown dog' /
find / -type f -exec grep -i 'the brown dog' {} \;
-exec {} +
форма будет делать меньше вилок, поэтому должна быть быстрее, чем-exec {} \;
. Возможно, вам придется добавить-H
(или-h
) кgrep
параметрам, чтобы получить точно эквивалентный результат.-r
опциюgrep
для второгоОтветы:
Я не уверен:
действительно то, что вы имели в виду. Это будет означать рекурсивный grep во всех не скрытых файлах и директориях
/
(но все же заглянуть внутрь скрытых файлов и каталогов внутри них).Предполагая, что вы имели в виду:
Несколько вещей, на которые стоит обратить внимание:
grep
реализации поддерживают-r
. И среди тех, кто это делает, поведение отличается: некоторые переходят по символическим ссылкам на каталоги при обходе дерева каталогов (что означает, что вы можете в конечном итоге просмотреть один и тот же файл несколько раз или даже выполнить бесконечные циклы), некоторые - нет. Некоторые будут смотреть внутри файлов устройств (и это займет довольно много времени,/dev/zero
например) или каналов или двоичных файлов ..., некоторые не будут.grep
начинает искать внутри файлов, как только обнаруживает их. Но пока он просматривает файл, он больше не ищет больше файлов для поиска (что, вероятно, также хорошо в большинстве случаев)Твой:
(убрал то,
-r
что здесь не имело смысла) ужасно неэффективно, потому что вы запускаете по одномуgrep
на файл.;
следует использовать только для команд, которые принимают только один аргумент. Более того, здесь, посколькуgrep
выглядит только в одном файле, он не будет печатать имя файла, поэтому вы не будете знать, где находятся совпадения.Вы не заглядывая внутрь файлы устройства, трубы, симлинки ..., вы не следующие ссылок, но вы по- прежнему потенциально смотрите внутри вещи , как
/proc/mem
.было бы намного лучше, потому что
grep
было бы выполнено как можно меньше команд. Вы получите имя файла, если только у последнего запуска не будет только одного файла. Для этого лучше использовать:или с GNU
grep
:Обратите внимание, что
grep
он не будет запущен, покаfind
не найдет достаточно файлов для его пережевывания, поэтому будет некоторая начальная задержка. Иfind
не будет продолжать поиск других файлов, покаgrep
не вернется предыдущий . Распределение и передача большого списка файлов оказывает некоторое (вероятно, незначительное) влияние, поэтому в целом он, вероятно, будет менее эффективным, чемgrep -r
тот, который не следует по символической ссылке или не заглядывает внутрь устройств.С инструментами GNU:
Как и выше,
grep
будет запущено как можно меньше экземпляров, ноfind
будет продолжаться поиск большего количества файлов, пока первыйgrep
вызов просматривает первый пакет. Это может или не может быть преимуществом, хотя. Например, данные, хранящиеся на вращающихся жестких дисках,find
иgrep
доступ к данным, хранящимся в разных местах на диске, замедляют пропускную способность диска, вызывая постоянное перемещение головки диска. В настройке RAID (гдеfind
иgrep
могут иметься доступ к разным дискам) или на SSD это может иметь положительное значение.В настройке RAID выполнение нескольких одновременных
grep
вызовов также может улучшить ситуацию. Все еще с инструментами GNU на хранилище RAID1 с 3 дисками,может значительно увеличить производительность. Однако обратите внимание, что вторая
grep
будет запущена только после того, как будет найдено достаточно файлов для заполнения первойgrep
команды. Вы можете добавить-n
опциюxargs
для того, чтобы это произошло раньше (и передавать меньше файлов заgrep
вызов).Также обратите внимание, что если вы перенаправляете
xargs
вывод на что-либо, кроме оконечного устройства, тоgreps
s начнут буферизовать свои выходные данные, что означает, что выходные данные этихgrep
s будут, вероятно, неправильно чередоваться. Вам придется использоватьstdbuf -oL
(там, где это доступно, например, в GNU или FreeBSD) их, чтобы обойти это (у вас все еще могут быть проблемы с очень длинными строками (обычно> 4 КБ)) или каждый из них записывает свои выходные данные в отдельный файл и объединяет их все в итоге.Здесь искомая строка является фиксированной (не является регулярным выражением), поэтому использование
-F
опции может иметь значение (маловероятно, посколькуgrep
реализации уже знают, как ее оптимизировать).Еще одна вещь, которая может иметь большое значение, это исправить языковой стандарт на C, если вы находитесь в многобайтовом языковом стандарте:
Чтобы не заглядывать внутрь
/proc
,/sys
... используйте-xdev
и укажите файловые системы, в которых вы хотите искать:Или удалите пути, которые вы хотите явно исключить:
источник
-exec
предиката на страницеЕсли
*
вgrep
вызове не важно для вас , то первый должен быть более эффективным , так как только один экземплярgrep
запускается, и вилки не свободны. В большинстве случаев это будет быстрее, даже если,*
но в крайних случаях сортировка может изменить это.Там может быть и другими
find
-grep
структуры , которые работают лучше , особенно с большим количеством мелких файлов. Чтение большого количества записей в файлах и инодов одновременно может повысить производительность вращающихся носителей.Но давайте посмотрим на статистику системных вызовов:
находить
только grep
источник
-r
флагgrep
при использованииfind
. Вы можете видеть, что он снова и снова просматривал одни и те же файлы, сравнивая количествоopen
произошедших событий.-r
должны быть безвредными, так как-type f
гарантии, что ни один из аргументов не является каталогом. Множественныеopen()
значения более вероятны вплоть до других файлов, открываемыхgrep
при каждом вызове (библиотеки, данные о локализации ...) (спасибо за редактирование моего ответа)Если вы используете SSD и время поиска незначительное, вы можете использовать GNU параллельно:
Это выполнит до 8 процессов grep одновременно, в зависимости от
find
найденного.Это сломает жесткий диск, но SSD должен справиться с этим довольно хорошо.
источник
Еще одна вещь, на которую следует обратить внимание, заключается в следующем.
Будут ли какие-либо из каталогов, которые grep должен будет рекурсивно проходить, содержать больше файлов, чем параметр nofile вашей системы ? (например, количество дескрипторов открытых файлов, по умолчанию 1024 на большинстве дистрибутивов Linux)
Если это так, то определенно стоит искать, так как некоторые версии grep будут выдавать слишком длинную ошибку из списка аргументов при попадании в каталог с большим количеством файлов, чем задано параметром максимального количества открытых файлов.
Просто мои 2 ¢.
источник
grep
бомбить? По крайней мере, с GNU grep, если вы дадите путь с трейлингом/
и-R
будете его использовать, вы будете просто перебирать каталоги. Оболочка не собирается расширять ничего , если не дать оболочки-шарики. Таким образом, в данном примере (/*
) только содержимое/
материи, а не подпапок, которые будут просто перечисленыgrep
, не передается в качестве аргумента из оболочки.