У меня проблемы с поиском по ВСЕМ каталогам одновременно с 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
.