Intereting Posts
Подключиться к Linux-машине за брандмауэром pepperflashplugin-nonfree: ERROR: не удалось получить информацию о статусе из google: W: для следующих идентификаторов ключей нет открытого ключа Настройка последовательного драйвера sc16is7xx Как удалить стандартные «доверенные» корневые центры сертификации u-boot не может сохранять параметры среды, если указан «bootm» где $ PATH получает свои значения из (osx)? Политика удаления iptables Как установить режим видео в linux с помощью kms / drm? Поиск строк, которые находятся в одном файле, но не в других, используя Unix и Awk Как конвертировать пакет avis в mp4s? Сценарий оболочки для записи выбранных полей в одну строку изменение разрешений ldd с 755 на неисполнение и обоснование безопасности Отключение аутентификации паролей ssh ​​не работает на моем debian VPS Gnome3 – добавление клавиатуры «Пользовательские ярлыки» с использованием dconf без необходимости выхода из системы Raid 0 Установка Linux не позволяет установить grub

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

Я хочу рекурсивно находить файлы в исходном дереве по содержанию. Я пробовал использовать 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" *