Как использовать grep для поиска текста во ВСЕХ папках?

Как использовать grep для поиска текста во ВСЕХ папках?

У меня проблемы с поиском по ВСЕМ каталогам одновременно с grep. Когда я использую команду:

find . -name "*.txt" | xargs grep texthere

Это занимает целую вечность, а затем выдает ошибку «нет такого файла или каталога».

Почему это происходит и нет ли ничего проще, чем grep? Или я использую неправильную команду?

решение1

Если у вас есть GNU grep, то сам grep поддерживает опцию «-r» для рекурсивного поиска, как предложил @Ouroborus.

Если, к сожалению, ваш grep не поддерживает такую ​​опцию, как в SunOS, вы можете использовать следующие команды:

find . -name "*.txt" -exec grep -n your_pattern {} /dev/null \;

Хитрость /dev/nullдобавляется для того, чтобы гарантировать, что каждое выполнение grep имеет два файла (файл, соответствующий *.txt, и /dev/null), заставляя его печатать имена файлов, в которых выполняется поиск. И вы можете добавить -type fопцию findдля уточнения области действия find.

решение2

Как вэтот ответ, вам, вероятно, лучше подойдет:

grep -rnw '/path/to/somewhere/' -e "pattern"

  • -rили -Rрекурсивно,
  • -nэто номер строки, и
  • -wстенды соответствуют всему слову.
  • -l(строчная буква L) может быть добавлена, чтобы просто указать имя файла для соответствующих файлов.

решение3

Если вы получаете ошибки о разрешениях (вы не говорите, что делаете), то я предполагаю, что вы находитесь либо в корневом каталоге ( /), либо в каком-то пути, где у вас нет разрешения на чтение всех файлов, например в /etcили в /var. Но поскольку вы говорите, что это занимает ужасно много времени, я больше склоняюсь к первому предположению (корневой каталог).

Если вы хотите искать абсолютновсефайлы навесьсистема, то то, что вы делаете, в значительной степени правильно. Этоволязанимает много времени, что бы вы ни делали. Это просто ужасно много файлов для поиска.

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

На данный момент у вас есть

$ find . -name "*.txt" | xargs grep texthere

Поскольку, судя по всему, вас интересуют только простые текстовые файлы, мы можем исключить любые другие типы файлов (исполняемые файлы):

$ find / -type f \! -perm -o=x -name "*.txt" | xargs grep texthere

Я заменил .на /здесь, потому что это то место, где ядуматьвы (поправьте меня, если я ошибаюсь). Я также уточняю, что я хочуфайлы( -type f) которыене исполняемый( \! -perm -o=x) ( !необходимо экранировать, чтобы ваша оболочка не делала с ней странных вещей).

Теперь, есть еще пара вещей, которые мы можем сделать. Одна из них — безопасность, а другая можетвозможнонемного увеличить скорость.

Некоторые имена файлов могут содержать пробелы или другие странные символы, которые мы обычно не хотим видеть в именах файлов. Чтобы иметь возможность правильно передавать их между findи grepмы делаем

$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 grep texthere

Это ( -print0) означает, что каждое имя файла будет разделено символом nul( \0), а не пробелом. И соответствующая опция для xargsполучения этих nulимен файлов с разделителями - -0.

Я полагаю, что именно потому, что вы не используете эти две опции, вы и получаете ошибки «такой файл или каталог отсутствует».

Скорость — это то, что fgrep. Это утилита, которая в точности эквивалентна grep -Fтой, которую вы должны использовать, если ваша строка поиска представляет собой простую текстовую строку без регулярных выражений.

Итак, если у вас есть простая текстовая строка и вы хотите найти ее в каждом файле во всей системе:

$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 fgrep texthere

Что касается разрешений... Очевидно, что будут файлы, которые вы не сможете прочитать. Вы можете либо запустить findи fgrepс sudoдобавлением к ним:

$ sudo find ... | xargs -0 sudo fgrep texthere

Или вы можете попробовать создать другой -permфлаг find(а также заставить его игнорировать каталоги, в которые вы не можете войти), но это займет слишком много времени и приведет к смехотворно длинной командной строке, поэтому я не буду этого делать здесь.

Или вы можете просто sudo -sполучить root-оболочку и запустить ее оттуда... но я бы не советовал этого делать, потому что люди склонны портить свои системы, забывая, что они root.

ДРУГОЕ РЕШЕНИЕбыло бы использовать locateкоманду для поиска всех .txtфайлов во всей системе. locateКоманда не ищет в файловой иерархии, а вместо этого использует базу данных (которая обычно обновляется ежедневно, так что невсеФайлы могут быть там). База данных содержит файлы только в каталогах, доступных всем пользователям, поэтому, если вы удалили права на чтение для своих собственных каталогов, ваших файлов там не будет.

Итак, заменим findкоманду выше на locateпочти эквивалентную:

$ locate '*.txt' -0 | xargs -0 fgrep texthere

Опция -0(или --nullв некоторых системах) соответствует --print0опции find.

Связанный контент