Я не думаю, что вы можете сделать это за один проход, используя grep
.
Двухпроходное решение grep
Это решение использует find
для передачи файлов в текущем каталоге в цикл while, который, в свою очередь, выполняет требуемый grep'ing:
find . -maxdepth 1 -type f -print0 | while IFS= read -r -d $'\0' file; do
grep -q '/mo' "$file" || grep -l '/fo' "$file"
done
Однопроходное решение GNU awk
parse.awk
BEGINFILE { f1 = f2 = 0 }
$0 ~ pat1 { f1 = 1 }
$0 ~ pat2 { f2 = 1 }
ENDFILE { if(f1 && !f2) print FILENAME }
Запустите это так:
awk -f parse.awk pat1='/fo' pat2='/mo' *
объяснение
GNU awk имеет функции BEGINFILE
и ENDFILE
которые представляют собой блоки, выполняемые в начале и конце входного файла. Это позволяет нам переворачивать флаги, когда узоры видны.
Приведенный выше пример устанавливает два флага, f1
и f2
, в зависимости от того, найдены ли pat1
и pat2
в текущем входном файле. Таким образом, блок ENDFILE
знает, присутствовали ли оба шаблона в текущем входном файле, и может выполнить соответствующий тест.