8

Я хочу найти файлы, содержащие две строки вместе, например, файл содержит как string1 и string2 .

Я хочу полный путь файлов в выводе. Я не хочу видеть предупреждения "отказано в разрешении".

5 ответов5

12
grep -l string2 `grep -l string1 /path/*`

который так же, как

grep -l string2 $(grep -l string1 /path/*)

Изменить: вот почему grep string1 /path/* | grep string2 не делает то, что я думаю, что alwbtc хочет.

$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$

Ничего не найдено, но файл b содержит обе строки.

Вот что я думаю, что alwbtc хочет

$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
2

Труба один grep в другой:

grep "string1" /path/to/files/* | grep "string2"

1

Вот эквивалентная команда для ответа RedGrittyBrick:

ack string2 $(ack string1 -l)

Работает так же (за исключением того, что ack по умолчанию ищет текущий каталог рекурсивно). Содержимое в $() ищет string1 но -l выводит только имена файлов, в которых была найдена эта строка. Затем они передаются в качестве аргументов во внешнюю команду, что означает, что string2 ищется только в этом списке файлов.

0

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

grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)

Опция -s подавит сообщения об ошибках
Опция -r позволяет искать строки в произвольно вложенных каталогах
! в сочетании с && echo /dev/null гарантирует, что команда не будет зависать. В противном случае, если inner grep не найдет файл, он ничего не выведет, так что outer grep будет бесконечно ждать ввода для поиска. Это решение выводит /dev/null в этих случаях, поэтому outer grep будет искать STRING1 в /dev/null где он должен ничего не находить.

0
comm -12 <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort) <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort)

или менее избыточно:

search_files () { str="$1"; shift; grep -Fl "$str" "$@" 2>/dev/null | sort; }
comm -12 <(search_files "STRING1" /path/to/files/*) <(sf "STRING2" /path/to/files/*)

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .