Я нахожусь в папке с большим количеством .txt
файлов, я хотел бы найти все файлы, которые содержат stringA
, но не содержат stringB
(они не обязательно находятся в одной строке). Кто-нибудь знает, как это сделать?
решение1
Если имена ваших файлов не содержат пробелов, табуляций, символов новой строки (при условии, что это неизмененный файл $IFS
) или подстановочных знаков и не начинаются с -
, и если ваша grep
система поддерживает эту -L
опцию, вы можете сделать это следующим образом:
$ cat file1
stringA
stringC
$ cat file2
stringA
stringB
$ grep -L stringB $(grep -l stringA file?)
file1
Выполненный grep
в подоболочке $()
, выведет все имена файлов, которые содержат stringA
. Этот список файлов является входными данными для основной grep
команды, которая выводит список всех файлов, которые не содержат stringB
.
Отman 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.)
решение2
С помощью инструментов GNU:
grep -lZ stringA ./*.txt |
xargs -r0 grep -L stringB
-L
, -Z
, -r
, -0
иногда являются расширениями GNU, но не всегда встречаются в некоторых других реализациях.
решение3
#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
Проверив ответ Бернхарда:
grep -Le "string B" $(grep -le "string A" `ls`)
Если имя файла содержит пробелы:
grep -L stringB $(grep -l stringA `ls -l | tail -n+2 | awk '{print $NF}' | sed -e 's/\s/\\ /g'`