У меня около 500 строк, и я хочу найти файлы, которые их содержат внутри каталога, и получить имена файлов, которые содержат строки. До сих пор я использовал:
find -name 'LYFNRE.*' -exec grep -f file1.txt {} \; -print
но проблема в том, что строка может быть найдена во многих файлах, поэтому трудно найти, какие строки присутствуют, а какие отсутствуют из-за огромного вывода. Можете ли вы помочь мне распечатать строки с соответствующими именами файлов, где они были найдены.
решение1
Вы должны просто позволить grep
дать вам имена файлов. GNU grep
может сделать это:
grep -HFf ../strings.txt *
Это предоставит вам вывод, который выглядит следующим образом:
[filename]:[matched_line]
...для каждого совпадения в каждом файле в каталоге. Вы также можете получить номера строк:
grep -HnFf ../strings.txt *
...которая обеспечивает...
[filename]:[line_number]:[matched_line]
решение2
Проблема в том, что вы передаете один файл за раз в grep
. Когда grep
видит один файл в своей командной строке, он предполагает, что вы точно знаете, где ищете, поэтому он не отображает имя файла перед совпадениями.
Трюк, чтобы заставить grep
всегда выводить имя файла, — это также передать /dev/null
(где не будет никакого совпадения). В некоторых реализациях grep есть опция для этого: -H
.
Кроме того, вы можете использовать -exec … {} +
вместо -exec … {} \;
для выполнения программы для многих файлов за один раз. Это быстрее. Вам все равно следует передать /dev/null
или -H
, поскольку может случиться, что команда будет вызвана только для одного файла, либо потому, что есть один совпадающий файл, либо потому, что есть много совпадений, требующих , чтобы grep
был вызван несколько раз, и один раз касается одного файла.
find -name 'LYFNRE.*' -exec grep -f file1.txt /dev/null {} +
GNU grep и последние реализации BSD (включая OSX) поддерживают опции для grep
рекурсивного вызова без необходимости использования find
.
grep -R --include='LYFNRE.*' -f file1.txt -H .
В качестве альтернативы вы можете сделать рекурсивную подстановку в вашей оболочке. В zsh это работает из коробки. В bash вам нужно shopt -s globstar
сначала запустить, и будьте осторожны, что bash рекурсивно использует символические ссылки на каталоги (в отличие find
от zsh).
grep -f file1.txt /dev/null **/LYFNRE.*
решение3
используйте egrep:
egrep -n "str1|str2|str3" file_names
-n выведет номер строки в указанном файле, где была найдена строка