grep -R
(за исключением модифицированного GNU, grep
найденного в OS / X 10.8 и выше), следует ~/Documents
символьные ссылки , поэтому, даже если в нем всего 100 ГБ файлов , может существовать символическая ссылка, /
например, и вы в конечном итоге сканируете всю файловую систему, включая файлы как /dev/zero
. Используйте grep -r
с более новым GNU grep
, или используйте стандартный синтаксис:
find ~/Documents -type f -exec grep Milledgeville /dev/null {} +
(однако обратите внимание, что статус выхода не будет отражать тот факт, что шаблон соответствует или нет).
grep
находит линии, которые соответствуют шаблону. Для этого он должен загружать одну строку за раз в памяти. GNU, grep
в отличие от многих других grep
реализаций, не имеет ограничения на размер строк, которые он читает, и поддерживает поиск в двоичных файлах. Таким образом, если у вас есть файл с очень большой строкой (то есть с двумя символами новой строки, расположенными очень далеко), больше, чем доступная память, он потерпит неудачу.
Это обычно происходит с разреженным файлом. Вы можете воспроизвести это с:
truncate -s200G some-file
grep foo some-file
Это трудно обойти. Вы можете сделать это как (все еще с GNU grep
):
find ~/Documents -type f -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} +
Это преобразует последовательности символов NUL в один символ новой строки перед подачей ввода в grep
. Это касается случаев, когда проблема связана с редкими файлами.
Вы можете оптимизировать это, делая это только для больших файлов:
find ~/Documents -type f \( -size -100M -exec \
grep -He Milledgeville {} + -o -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} + \)
Если файлы не редки, и у вас есть версия GNU grep
до 2.6
, вы можете использовать эту --mmap
опцию. Строки будут отображаться в памяти, а не копироваться туда, что означает, что система всегда может восстановить память, перемещая страницы в файл. Эта опция была удалена в GNU grep
2.6
grep
можно отбросить буферы, которые он обработал до сих пор. Вы можетеgrep
выводить наyes
неопределенный срок без использования более нескольких килобайт памяти. Проблема заключается в размере линий.--null-data
также может быть полезна опция GNU grep . Это заставляет использовать NUL вместо новой строки в качестве ограничителя входной строки.Я обычно делаю
Я попробовал кучу методов, и нашел, что это самый быстрый. Обратите внимание, что это не очень хорошо обрабатывает файлы с пробелами в имени файла. Если вы знаете, что это так, и имеете GNU-версию grep, вы можете использовать:
Если нет, вы можете использовать:
Который будет
exec
grep для каждого файла.источник
find -print0 | xargs -0 grep -ne 'expression'
find -print0
иxargs -0
к настоящему моменту: все три BSD, MINIX 3, Solaris 11,…Я могу придумать несколько способов обойти это:
Вместо того, чтобы подбирать все файлы одновременно, делайте один файл за раз. Пример:
Если вам нужно только знать, какие файлы содержат слова, сделайте
grep -l
вместо этого. Поскольку grep прекратит поиск после первого попадания, ему не нужно будет продолжать читать огромные файлы.Если вы также хотите получить реальный текст, вы можете связать две отдельные команды:
источник
grep
выходных данных используется разделитель, допустимый в именах файлов). Вы также должны цитировать$file
.for
к обработке файла как двух аргументов)Я копирую диск размером 6 ТБ для поиска потерянных данных и получаю исчерпанную память - ошибка. Это должно работать и для других файлов.
Решение, которое мы придумали, состояло в том, чтобы читать диск кусками, используя dd, и подбирать куски. Это код (big-grep.sh):
источник