Мне нужно найти все экземпляры данной строки во всей файловой системе, потому что я не помню, в какие файлы конфигурации, скрипт или какие-либо другие программы я ее поместил, и мне нужно обновить эту строку с помощью новой.
Я пробовал с помощью следующей команды
`grep -nr 'Needle' / --exclude-dir = .svn | mail myaddress@example.com -s 'Ссылки на xxx'
Если я запустил эту команду в небольшом каталоге, она даст мне нужный результат в виде
/path1/:nn:line containing needle
/path2/:nn:line containing needle
где / path1 - полный путь к файлу, nn - строка, содержащая иглу, а последнее поле - это содержимое строки.
Однако, когда я запускаю команду в корневом каталоге, процесс grep через некоторое время зависает. Я запускаю этот скрипт около 8 часов назад, и даже в небольшой файловой системе (менее 5 ГБ) он не заканчивается, и если я запускаю top
или ps
процесс кажется спящим
root 24909 0.0 0.1 3772 1520 pts/1 S+ Feb10 0:15 grep -nr needle / --exclude-dir=.svn
Почему это не заканчивается? Есть ли лучший способ сделать это (это одноразовая работа, мне не нужно выполнять ее более одного раза)
Спасибо.
Обновление: я нашел рабочее решение с find и xargs, которое, похоже, работает и использует меньше системных ресурсов, чем решение find -exec. Вот моя последняя командная строка:
find /{boot,etc,home,lib,lost+found,opt,root,sbin,usr,var} -type f -print0 | xargs -r0 grep -nr 'needle' | mail myaddress@example.com -s 'References on xxx'
Я использовал /{dir1,dir2,...,dirn}
синтаксис, потому что мне нужны выходные строки с полным путем, включая ведущую косую черту, и таким образом вы можете использовать команду без cd /
т.е. из любого каталога.
Вы можете попробовать использовать для этого find + xargs + grep, вроде:
find /there -type f :MaybeSomeRestrictingFlagsLikeSizeNotBigger500MB_or_FS_type_if_u_know_its_exactly_on_EXT3_AndSoOn: -print0 | xargs -0r grep needle /dev/null
(/ dev / null заставляет grep печатать имя файла, даже если был найден только один файл)
В файловой системе есть некоторые файлы, которые не являются настоящими файлами, а являются "перехватчиками" ядра. Некоторые из них можно читать бесконечно. Пытаться
grep foo /dev/zero
чтобы увидеть это в действии. Будьте готовы остановить его с помощью ctrl-C, прежде чем он возьмет на себя всю систему.
Если бы я хотел делать то, что делаете вы, я бы перечислил подкаталоги /
которые я хотел просканировать, и убедитесь, что я проверял только текстовые файлы, возможно, с
cd /
find boot etc home lib lost+found media mnt opt root sbin tmp usr var -type f -exec grep needle {} /dev/null \;
Обратите внимание, как выглядит список не содержать /dev
, /proc
, /sys
или /selinux
.
Я не знаю, почему это не заканчивается, но в таких случаях обычно работает «fgrep -R».
Вы можете исключить dev и proc из этой команды. Я бы сделал это с помощью find и исключил специальные файлы:
find . -type f -exec grep -H "My search string" '{}' \; -print
Как отмечали некоторые другие, ошибка возникает из-за того, что вы используете grep для некоторых «файлов», которые будут давать странные результаты. Например, grep XXX / dev / zero будет продолжаться вечно.
Сначала я бы исключил из поиска такие каталоги, как / dev / и / proc /. Другой способ - искать только «файлы» и никаких других типов.
Также, если ваш список аргументов в grep слишком длинный, вы получите эту ошибку:
bash: /bin/grep: Argument list too long
Вы можете обойти это с помощью цикла, например:
for i in `find -type f /`; do grep -H "sample string" $i; done
Или выполнив его из find, что бы ни плавало на вашей лодке.
find / -type f -exec grep -H "sample string" '{}' \; -print
Это должно выполнить поиск, а затем grep для каждого файла. Хотя некоторые указали, что неэффективно запускать grep каждый раз, когда вы находите файл, вам придется делать что-то, что будет «неэффективным», потому что вам буквально придется искать эту строку в каждом файле.