Respostas:
grep -l string2 `grep -l string1 /path/*`
que é o mesmo que
grep -l string2 $(grep -l string1 /path/*)
Edit: aqui está porque grep string1 /path/* | grep string2não faz o que eu acho que alwbtc.
$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$
Nada foi encontrado, mas o arquivo b contém as duas strings.
Aqui está o que eu acho que o alwbtc quer
$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
-lopção para os dois comandos serem considerados iguais.
Coloque um grepno outro:
grep "string1" /path/to/files/* | grep "string2"
Aqui está o comando ack equivalente à resposta do RedGrittyBrick :
ack string2 $(ack string1 -l)
Funciona da mesma maneira (exceto, ackpor padrão, pesquisa o diretório atual recursivamente). O conteúdo nas $()pesquisas, string1mas -lgera apenas os nomes de arquivos em que essa sequência foi encontrada. Eles são passados como argumentos para o comando externo, o que significa que string2é pesquisado apenas dentro dessa lista de arquivos.
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)
ou menos redundante:
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/*)
Isso funcionará se as strings estiverem em linhas diferentes do mesmo arquivo e também evitará falsos positivos se um nome de arquivo contiver uma das strings.
Para elaborar a solução do @ RedGrittyBrick, que apresenta uma falha ao executar o comando autônomo, além de suprimir a saída de erro conforme o esperado e encontrar arquivos recursivamente, você pode considerar
grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)
-sA opção suprimirá as mensagens de erro. A
-ropção permite procurar seqüências de caracteres em diretórios aninhados arbitrariamente,
!combinadas com && echo /dev/nullgarantias de que o comando não será desligado. Caso contrário, se inner grepnão encontrar nenhum arquivo, ele não produzirá nada, de modo que outer grepaguardará indefinidamente a entrada para pesquisar. Esta solução saídas /dev/nullnestes casos assim outer grepvai procurar STRING1em /dev/nullonde é suposto para não encontrar nada.
Eu estava procurando por uma maneira extensível de executar 2 ou mais strings e surgiu com isso:
grep -rl string1 path-to-files | xargs grep -l string2 | xargs grep -l string3
O primeiro grep encontra recursivamente os nomes dos arquivos que contêm string1dentro path-to-files.
Os resultados são canalizados para os xargsquais executa um ou mais comandos grep nesses arquivos string2.
Os resultados são então canalizados para outro xargscomando string3- é o mesmo que a primeira xargschamada, mas procurando uma sequência diferente.
O uso de xargsevitará problemas onde existem tantos resultados que a linha de comando resultante do uso de back-ticks é muito longa.
Para evitar os avisos, podemos redirecionar stderrpara /dev/null:
grep -rl string1 path-to-files 2>/dev/null | xargs grep -l string2
Não é necessário nas chamadas grep subsequentes, porque string1já foi encontrado dentro do arquivo, portanto, as permissões são boas.
-lopção de retornar os nomes dos arquivos em vez das linhas. Ele está usando o cifrão ou as aspas para passar essa lista comoFILEargumento para o segundo grep. Isso permite que o segundo grep pesquise a totalidade de cada arquivo encontrado, em vez das linhas individuais, como na minha solução.