Я хочу найти файлы, содержащие две строки вместе, например, файл содержит как string1
и string2
.
Я хочу полный путь файлов в выводе. Я не хочу видеть предупреждения "отказано в разрешении".
Я хочу найти файлы, содержащие две строки вместе, например, файл содержит как string1
и string2
.
Я хочу полный путь файлов в выводе. Я не хочу видеть предупреждения "отказано в разрешении".
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
Труба один grep
в другой:
grep "string1" /path/to/files/* | grep "string2"
Вот эквивалентная команда ack для ответа RedGrittyBrick:
ack string2 $(ack string1 -l)
Работает так же (за исключением того, что ack
по умолчанию ищет текущий каталог рекурсивно). Содержимое в $()
ищет string1
но -l
выводит только имена файлов, в которых была найдена эта строка. Затем они передаются в качестве аргументов во внешнюю команду, что означает, что string2
ищется только в этом списке файлов.
Чтобы уточнить решение @ 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
где он должен ничего не находить.
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/*)
Это будет работать, если строки находятся в разных строках одного и того же файла, а также позволит избежать ложных срабатываний, если имя файла содержит одну из строк.