Estoy en una carpeta con muchos .txt
archivos, me gustaría encontrar todos los archivos que contienen stringA
pero 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 grep
admite la -L
opción, puede hacerlo de la siguiente manera:
$ cat file1
stringA
stringC
$ cat file2
stringA
stringB
$ grep -L stringB $(grep -l stringA file?)
file1
El grep
ejecutado en el subshell $()
imprimirá todos los nombres de archivos que contengan stringA
. Esta lista de archivos es la entrada para el grep
comando 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
, -0
son 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'`