grep arquivos com padrão A, mas exclui arquivos com padrão B

grep arquivos com padrão A, mas exclui arquivos com padrão B

Quero usar grep em arquivos que incluam o padrão A (iwant), mas quero excluir arquivos que contenham o padrão B (idontwant).

Exemplo:

read -p "...what are you looking for: " iwant
read -p "...what should not be included: " idontwant

iwant="blue car" 
idontwant="red car"

Suponha que eu tenha os seguintes arquivos:

-rw-rw-r--.  1 terpentin terpentin  45 Jun  8 16:04 blue.car
-rw-rw-r--.  1 terpentin terpentin  44 Jun  8 16:05 mixed.car
-rw-rw-r--.  1 terpentin terpentin  40 Jun  8 16:04 red.car
find . -type f -print -exec cat {} \;

./mixed.car
blue car
red car
blue car

./red.car
red car
red car
red car

./blue.car
blue car
blue car
blue car

Como é possível obter apenas o arquivo "./blue.car" como resultado?

O conteúdo original inclui centenas de arquivos de texto longos, o que torna importante ser o mais eficiente possível em termos de recursos.

Responder1

Usar

find . -type f ! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -print

ou

find . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -print
  • Os termos (às vezes chamados de “predicados”) em um find comando são caracterizados comotestes(por exemplo,  -type f) eações(por exemplo,  -print-delete). Pode ser difícil descobrir na página de manual que -execé ao mesmo tempo um Açãoe um teste. Então, assim como
    encontrar . -type f -mtime -30 -name '*.txt' -readable -size +5teste 6 teste 7 teste 8
    restringe sucessivamente a pesquisa a arquivos que atendam a todos os critérios (satisfaçam todos os testes especificados), então
    encontrar . -execcmd1{} ';' -execcmd2{} ';' -execcmd3{} ';' …
    encontra arquivos para os quais todos os comandos foram bem-sucedidos.
  • Qualquer findteste pode ser negado (invertido) precedendo-o com !. Assim, find . ! -type dencontra arquivos simples, links simbólicos, pipes nomeados, soquetes e arquivos de dispositivos — tudo, exceto diretórios.
  • Observe que isso ! -exec grep …não é equivalente a -exec grep -v …-exec grep -v …encontrará arquivos que possuem pelo menos uma linha que não corresponde.  ! -exec grep …encontrará arquivos ondenãoas linhas coincidem.
  • A -qopção to grepé oficialmente sinônimo de --quiet, mas também significarápido. Ele não grava nenhuma saída (exceto talvez mensagens de erro, conforme aplicável), mas também sai assim que encontra uma correspondência - ele não lê todos os arquivos até o fim para encontrartodocorresponder. (É claro que, se um arquivo não contiver nenhuma correspondência, será grepnecessário lê-lo na íntegra para determinar isso.)
  • Então (DR) os comandos encontram os arquivos para os quais
    grep -q "$eu quero"     arquivo
    consegue e
    grep -q "$idontwant"arquivo
    falha (porque o precedemos com !).
  • Os dois comandos são funcionalmente equivalentes, mas podem ter desempenho diferente (ou seja, podem levar tempos diferentes para serem executados). Se apenas alguns arquivos contiverem as strings de pesquisa,
    encontrar . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -imprimir
    será mais rápido, pois grep "$iwant"eliminará a maioria dos arquivos. Se muitos dos arquivos contiverem ambas as strings, então
    encontrar . -digite f! -exec grep -q "$idontwant" {} ';' -exec grep -q "$eu quero" {} ';' -imprimir
    será mais rápido, pois ! grep "$idontwant"eliminará a maioria dos arquivos.

Responder2

Com GNU greppodemos realizar a extração do nome do arquivo com uma escolha criteriosa de opções regex e grep:

$ grep -lzPsr '(?s:(?=.*blue)(?!.*red))' .

Estamos operando o grep no modo slurp (-z), onde todo o arquivo é tratado como uma grande linha.

O -l listará os nomes dos arquivos que correspondem ao regex.

O -r será executado recursivamente em todos os arquivos no diretório atual e abaixo.

O -s silenciará o grep para não emitir nenhum aviso.

A regex procurará a presença de azul e ausência de vermelho em um arquivo para dizer sim.

O -P invoca o mecanismo regex Perl no grep para que possamos obter a vantagem dos regexes pcre.

informação relacionada