Encuentre archivos que contengan una cadena pero no la otra

Encuentre archivos que contengan una cadena pero no la otra

Estoy en una carpeta con muchos .txtarchivos, me gustaría encontrar todos los archivos que contienen stringApero que no contienen stringB(no necesariamente están en la misma línea). ¿Alguien sabe como hacer esto?

Respuesta1

Siempre que los nombres de sus archivos no contengan espacios, tabulaciones, nueva línea (suponiendo que no esté modificado $IFS) o caracteres comodín y no comiencen con -, y si grepadmite la -Lopción, puede hacerlo de la siguiente manera:

$ cat file1
stringA
stringC
$ cat file2
stringA
stringB
$ grep -L stringB $(grep -l stringA file?)
file1

El grepejecutado en el subshell $()imprimirá todos los nombres de archivos que contengan stringA. Esta lista de archivos es la entrada para el grepcomando principal, que enumera todos los archivos que no contienen stringB.

Deman grep

  -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v is specified by POSIX.)
  -L, --files-without-match
          Suppress normal output; instead print the name of each input file from which no output would normally have been printed.  The scanning will stop on the first match.
  -l, --files-with-matches
          Suppress normal output; instead print the name of each input file from which output would normally have been printed.  The scanning will stop on the first match.  (-l is specified by POSIX.)

Respuesta2

Con herramientas GNU:

grep -lZ stringA ./*.txt |
  xargs -r0 grep -L stringB

-L, -Z, -r, -0son extensiones de GNU a veces, pero no siempre se encuentran en otras implementaciones.

Respuesta3

#run loop for each file in the directory
for i in `ls -l | tail -n+2 | awk '{print $NF}'` ; do
   #check if file contains "string B" 
   #if true then filename is not printed
   if [[ `egrep "string B" $i | wc -l` -eq 0 ]] ; then
      #check if file contains "string A"
      #if false then file name is not printed
      if [[ `egrep "string A" $i | wc -l` -gt 0 ]] ; then
         #file name is printed only if "string A" is present and "string B" is absent
         echo $i
      fi
   fi
done

Después de comprobar la respuesta de Bernhard:

grep -Le "string B" $(grep -le "string A" `ls`)

Si el nombre del archivo contiene espacios:

grep -L stringB $(grep -l stringA `ls -l | tail -n+2 | awk '{print $NF}' | sed -e 's/\s/\\ /g'`

información relacionada