Estou em uma pasta com muitos .txt
arquivos, gostaria de encontrar todos os arquivos que contêm stringA
mas 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ê grep
suportar a -L
opçã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 grep
executado no subshell $()
imprimirá todos os nomes de arquivos que contêm stringA
. Esta lista de arquivos é a entrada para o grep
comando 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
, -0
sã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'`