grep archivos con patrón A pero excluye archivos con patrón B

grep archivos con patrón A pero excluye archivos con patrón B

Quiero buscar archivos que incluyan el patrón A (quiero) pero quiero excluir archivos que contengan el patrón B (quiero).

Ejemplo:

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

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

Simplemente suponga que tengo los siguientes archivos:

-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

¿Cómo es posible obtener como resultado sólo el archivo "./blue.car"?

El contenido original incluye cientos de archivos de texto largos, lo que hace que sea importante utilizar los recursos lo más eficientemente posible.

Respuesta1

Usar

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

o

find . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -print
  • Los términos (a veces llamados "predicados") en un find comando se caracterizan comopruebas(por ejemplo,  -type f) ycomportamiento(p. ej.,  -print-delete). Puede ser difícil descifrar en la página de manual que -execes a la vez una accióny un prueba. Entonces, así como
    encontrar . -tipo f -mtime -30 -nombre '*.txt' -legible -tamaño +5prueba 6 prueba 7 prueba 8
    reduce sucesivamente la búsqueda a archivos que cumplen todos los criterios (satisfacen todas las pruebas especificadas), por lo que
    encontrar . -ejecutivocomando 1{} ';' -ejecutivocomando 2{} ';' -ejecutivocomando 3{} ';' …
    busca archivos para los cuales todos los comandos tienen éxito.
  • Cualquier findprueba se puede negar (invertir) precediendola con !. Así, find . ! -type dbusca archivos simples, enlaces simbólicos, canalizaciones con nombre, sockets y archivos de dispositivos, todo excepto directorios.
  • Tenga en cuenta que ! -exec grep …no es equivalente a -exec grep -v …-exec grep -v …encontrará archivos que tengan al menos una línea que no coincida.  ! -exec grep …encontrará archivos dondeNolas líneas coinciden.
  • La -qopción grepes oficialmente sinónimo de --quiet, pero también significarápido. No escribe ningún resultado (excepto quizás mensajes de error, según corresponda), pero también sale tan pronto como encuentra una coincidencia; no lee todos los archivos hasta el final para buscarcadafósforo. (Por supuesto, si un archivo no contiene ninguna coincidencia, grepdebe leerlo en su totalidad para determinarlo).
  • Entonces (TL;DR) los comandos encuentran los archivos para los cuales
    grep -q "$quiero"     archivo
    tiene éxito y
    grep -q "$idontwant"archivo
    falla (porque lo precedimos con !).
  • Los dos comandos son funcionalmente equivalentes, pero pueden tener un rendimiento diferente (es decir, pueden tardar diferentes cantidades de tiempo en ejecutarse). Si sólo unos pocos archivos contienen las cadenas de búsqueda,
    encontrar . -tipo f -exec grep -q "$quiero" {} ';' ! -exec grep -q "$idontwant" {} ';' -imprimir
    Será más rápido, porque grep "$iwant"eliminará la mayoría de los archivos. Si muchos de los archivos contienen ambas cadenas, entonces
    encontrar . -tipo f! -exec grep -q "$idontwant" {} ';' -exec grep -q "$quiero" {} ';' -imprimir
    Será más rápido, porque ! grep "$idontwant"eliminará la mayoría de los archivos.

Respuesta2

Con GNU greppodemos realizar la extracción del nombre de archivo con una elección juiciosa de opciones regex y grep:

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

Estamos operando grep en modo slurp (-z) donde todo el archivo se trata como una línea grande.

El -l enumerará los nombres de los archivos que coinciden con la expresión regular.

El -r se ejecutará de forma recursiva en todos los archivos en el directorio actual a continuación.

El -s silenciará el grep para no emitir ninguna advertencia.

La expresión regular buscará la presencia de azul y la ausencia de rojo en un archivo para decir que sí.

-P invoca el motor de expresiones regulares Perl en grep para que podamos aprovechar las expresiones regulares pcre.

información relacionada