Рекурсивный поиск файлов по содержимому

Рекурсивный поиск файлов по содержимому

Я хочу рекурсивно найти файлы в моем исходном дереве по содержимому. Я попробовал следующее с помощью grep:

$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)

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

$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)

но вместо того, чтобы печатать имена файлов, я получаю только

(standard input)

выводится на stdout. Как мне это исправить, чтобы получить каждое имя файла и путь (для использования sedв нем)?

Что я хочу сделать: найти все файлы со printfстроками, которые также содержат %sи , bcm_errmsg(rv)а затем применить следующую команду sed к найденным файлам:

sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'

решение1

Я думаю, вы слишком усложняете. Чтобы найти строку fooво всех файлах, расположенных в текущем каталоге и подкаталогах, просто запустите

grep -r "foo" *

По умолчанию grep выводит совпадающую строку, к которой добавляется имя файла, в котором она была найдена.

Следующий код вместо этого выведет только имя файла без соответствующей строки:

grep -rl "foo" *

решение2

Следуя первоначальной идее @steeldriver, вы можете сделать:

egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'

решение3

grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
        /%s/!b
        /printf/!b
        /bcm_errstr(rv)/!b
        s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'

Сначала мы запускаем рекурсивный dir. из текущего dir, который сканирует файлы, которые содержат строки: printf, %s и bcm_errstr(rv) на одной строке, но, возможно, в любом порядке. Параметры, grepкоторые помогают нам это сделать, следующие:

  • -r=> рекурсивно запустит все файлы в текущем каталоге и ниже.
  • -l=> выведет список имен файлов, соответствующих критериям, а именно, все 3 строки на одной строке.
  • -Z=> выбранные имена файлов разделены нулем (\0) вместо обычного символа новой строки (\n), поэтому мы можем работать с любыми именами файлов.
  • -P=> включить механизм регулярных выражений Perl, с помощью которого мы можем использовать опережающий просмотр для определения того, находятся ли три строки в одной строке.

На другой стороне канала, xargsожидает получения имен файлов, разделенных \0. Затем он передает все эти имена файлов, насколько это возможно, в командную строку sed. Команда sed, которую вы уже знаете из вашего предыдущего вопроса, где она выполняет подпрограммы. только на тех строках, которые содержат 3 строки в одной строке.

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