Как искать текст по всей файловой системе?

53

Предполагая, что следует использовать инструмент grep, я бы хотел найти текстовую строку «800x600» во всей файловой системе.

Я пытался:

grep -r 800x600 /

но это не работает

Я считаю, что моя команда должна делать рекурсивно grep через все файлы / папки в корневом каталоге для текста «800x600» и выводить результаты поиска.

Что я делаю неправильно?

Level1Coder
источник
2
И под "это не работает" вы имеете в виду именно то, что? Не печатает ли вывод, зависает или печатает много Permission deniedошибок? Вы запускали его как root или обычный пользователь?
Алекс
Я получаю некоторую тягу, прежде всего, я был в моем домашнем каталоге пользователя, пытаясь выполнить команду. Так что теперь я cd / out для root. Затем я попробовал ту же команду, что и выше, и я получаю много ошибок «Отказано в доступе». Хорошо, теперь я пытаюсь использовать sudo grep -r 800x600 /, а затем получаю / proc / sysrq-trigger: Ошибка ввода / вывода
Level1Coder
Хм, не знаю, почему это не сработает. Вы можете игнорировать ошибки доступа, делая grep -r 800x600 / 2>/dev/null. Вы также можете попробовать запустить его как root.
Тотор

Ответы:

64

Обычно я использую этот стиль команд для запуска grepнескольких файлов:

find / -xdev -type f -print0 | xargs -0 grep -H "800x600"

На самом деле это составляет список всех файлов в системе, а затем для каждого файла выполняется grepс заданными аргументами и именем каждого файла.

-xdevАргумент говорит находке , что он должен игнорировать другие файловые системы - это хорошо для избежания специальных файловых систем , таких как /proc. Однако он также будет игнорировать обычные файловые системы - поэтому, если, например, ваша папка / home находится в другом разделе, она не будет искать - вам нужно будет сказать find / /home -xdev ....

-type fозначает поиск только файлов, поэтому каталоги, устройства и другие специальные файлы игнорируются (он все равно будет преобразовываться в каталоги и выполняться grepв файлах внутри - он просто не будет выполняться grepв самом каталоге, что в любом случае не будет работать). И -Hопция grepсказать ему всегда печатать имя файла в его выводе.

findпринимает все виды опций для фильтрации списка файлов. Например, -name '*.txt'обрабатывает только файлы, заканчивающиеся на .txt. -size -2Mозначает файлы размером менее 2 мегабайт. -mtime -5означает файлы, измененные за последние пять дней. Объедините их вместе с -a for и и -o for или и используйте '('скобки ')'для группировки выражений (в кавычках, чтобы оболочка не могла их интерпретировать). Так, например:

find / -xdev '(' -type f -a -name '*.txt' -a -size -2M -a -mtime -5 ')' -print0 | xargs -0 grep -H "800x600"

Взгляните, man findчтобы увидеть полный список возможных фильтров.

Ричард Даунер
источник
2
Обратите внимание, что -xdevбудут исключены все другие файловые системы, а не только специальные. (например, если вы /homeсмонтировали отдельный раздел, он не будет найден.)
cjm
Я попытался запустить каждый из них, но оба возвращают ошибку -find: paths must precede expression: /
Level1Coder
1
Примечание. Когда регулярные выражения не требуются, «fgrep» значительно быстрее, чем «grep», что будет иметь большое значение при поиске большого дерева.
Натан Кидд
1
Вы можете избежать, xargsвозможно, большей эффективности, делая find / -xdev -type f -exec grep -H '800x600' +.
Тотор
3
Нет, +знак в конце findкоманды фактически делает то же самое xargs: он порождает один grepпроцесс с несколькими аргументами.
Тотор
14

Обычно вы не захотите искать ВСЕ в системе. Linux использует файловые узлы для всего, поэтому некоторые «файлы» - это не те вещи, которые вы хотели бы искать. Например, /dev/sdaэто физическое блочное устройство для вашего первого жесткого диска. Вы, вероятно, хотите искать в смонтированных файловых системах, а не на устройстве с необработанным диском. Также есть то, /dev/randomчто выплевывает случайные данные каждый раз, когда вы читаете их. Поиск, который не имеет большого смысла. /procФайловая система также является проблематичной в вашем случае.

Я бы порекомендовал одну из двух вещей.

  1. Не ищите в корне, ищите только места, которые могут быть полезны. Поиск /homeили /usrили /etcотдельно. Информация, которую вы ищете, скорее всего, относится к определенному типу, так что, скорее всего, она будет в определенной папке. Настройки конфигурации должны быть в /etc. Ваши личные данные должны быть в /home. Ограничение поиска основной областью, подобной этой, значительно уменьшит ваши проблемы с рекурсивными программами.

  2. Исключите использование проблемных областей --exclude-dirи набор вещей, которые, как вы знаете, вам не нужны, вот так:
    grep -r --exclude-dir /proc --exclude-dir /dev --exclude-dir /tmp --exclude-dir /lost+found

Наконец, нередки случаи, когда при выполнении большого рекурсивного grep встречается несколько ошибок с отказом в разрешении. При обычном использовании есть файлы, которые ваш пользователь может не прочитать. Пока это всего лишь несколько нечетных файлов, а не такие вещи, как необработанное устройство для ваших жестких дисков или всей файловой системы proc, можно просто игнорировать ошибки. На самом деле вы можете сделать это в командной строке, отправив все ошибки никогда не приземляясь:

grep -r search_string /path 2> /dev/null
Калеб
источник
3
-Iисключить двоичный файл
Рахул Патил
2

Для простоты я бы предложил ack-grep . Ссылка показывает много случаев, когда ack-grepэто лучший вариант.

Для использования есть, после установки:

ack-grep pattern /
bbaja42
источник
Спасибо, что порекомендовали это, но я запустил это, и это не дало мне результатов поиска, которые я ожидал. Похоже, мне нужно будет настроить многие параметры, чтобы получить то, что я хочу. На данный момент ответ Ричарда работает прямо из коробки. Посмотрим на это в будущем, так как это кажется полезным.
Level1Coder
1

Другой способ взглянуть на это так:

grep -r /* | grep "800x600"
maniat1k
источник
0

* тогда я получаю / proc / sysrq-trigger: Ошибка ввода / вывода

Ваша команда работает, вы получаете эту ошибку, потому что вы пытаетесь сканировать запущенные процессы на наличие строки.

Я рекомендую исключить системные каталоги с

grep -exclude-dir = {proc, sys} "800x600" /

Koffee
источник
-3

просто правильно

grep -r "800x600" /

-Что не так в вашей текущей команде - это кавычки "". Всегда помещайте строковый аргумент grepв кавычки.

Амита
источник
3
Это не проблема здесь. Вам не нужно заключать в кавычки этот конкретный тип аргумента grep. Попробуйте, и вы увидите. Поместите строку "800x600" в файл, а затем, grep 800x600 fileи вы увидите, что она работает просто отлично. У ОП явно другая проблема.
SLM