Encontre arquivos contendo uma string, mas não a outra

Encontre arquivos contendo uma string, mas não a outra

Estou em uma pasta com muitos .txtarquivos, gostaria de encontrar todos os arquivos que contêm stringAmas não contêm stringB(não estão necessariamente na mesma linha). Alguém sabe como fazer isso?

Responder1

Contanto que seus nomes de arquivos não contenham espaços, tabulações, nova linha (assumindo um $IFS) ou caracteres curinga não modificados e não comecem com -, e se você grepsuportar a -Lopção, você pode fazer isso da seguinte maneira:

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

O grepexecutado no subshell $()imprimirá todos os nomes de arquivos que contêm stringA. Esta lista de arquivos é a entrada para o grepcomando principal, que lista todos os arquivos que não contêm 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.)

Responder2

Com ferramentas GNU:

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

-L, -Z, -r, -0são extensões GNU às vezes, mas nem sempre encontradas em algumas outras implementações.

Responder3

#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

Depois de verificar a resposta de Bernhard:

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

Se o nome do arquivo contiver espaços:

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

informação relacionada