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

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

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

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

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

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

 (standard input) 

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

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

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

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

 egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/' 
 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 ' 

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

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

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

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

 grep -r "foo" * 

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

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

 grep -rl "foo" *