Eu não acho que você pode fazer isso com um passe usando grep
.
Uma solução grep de duas passagens
Esta solução usa find
para passar arquivos no diretório atual para um loop while, que por sua vez faz o grep'ing desejado:
find . -maxdepth 1 -type f -print0 | while IFS= read -r -d $'BEGINFILE { f1 = f2 = 0 }
$0 ~ pat1 { f1 = 1 }
$0 ~ pat2 { f2 = 1 }
ENDFILE { if(f1 && !f2) print FILENAME }
' file; do
grep -q '/mo' "$file" || grep -l '/fo' "$file"
done
Uma solução de GNU awk de uma passagem
parse.awk
awk -f parse.awk pat1='/fo' pat2='/mo' *
Execute assim:
find . -maxdepth 1 -type f -print0 | while IFS= read -r -d $'BEGINFILE { f1 = f2 = 0 }
$0 ~ pat1 { f1 = 1 }
$0 ~ pat2 { f2 = 1 }
ENDFILE { if(f1 && !f2) print FILENAME }
' file; do
grep -q '/mo' "$file" || grep -l '/fo' "$file"
done
Explicação
O GNU awk possui o recurso BEGINFILE
e ENDFILE
, que são blocos executados no início e no final de um arquivo de entrada. Isso nos permite virar bandeiras quando os padrões são vistos.
O exemplo acima define os dois sinalizadores, f1
e f2
, com base em se pat1
e pat2
forem encontrados no arquivo de entrada atual. Assim, o bloco ENDFILE
sabe se ambos os padrões estavam presentes no arquivo de entrada atual e pode realizar o teste apropriado.