Como você já está usando as opções específicas do GNU ( -L
), você pode fazer:
grep -lZ -- "must have" *.txt | xargs -r0 grep -L -- "cannot have"
A idéia é usar -Z
para imprimir a lista de nomes de arquivos delimitados por NUL e usar xargs -r0
para passar essa lista como argumentos para o segundo grep
.
A substituição de comandos, por padrão, divide em espaço, tabulação e nova linha (e NUL em zsh
). Os shells semelhantes a Bourne, além de zsh
, também executam globbing em cada palavra resultante dessa divisão.
Você poderia fazer:
IFS='
' # split on newline only
set -f # disable globbing
grep -L -- "cannot have" $(
set +f # we need globbing for *.txt in this subshell though
grep -l -- "must have" *.txt
)
Mas isso ainda quebraria em nomes de arquivos contendo caracteres de nova linha.
Em zsh
(e zsh
apenas), você pode fazer:
IFS=$'grep -L -- "cannot have" ${(ps:grep -lZ -- "must have" *.txt | xargs -r0 grep -L -- "cannot have"
:)"$(grep -lZ -- "must have" *.txt)"}
'
grep -L -- "cannot have" $(grep -lZ -- "must have" *.txt)
Ou:
IFS='
' # split on newline only
set -f # disable globbing
grep -L -- "cannot have" $(
set +f # we need globbing for *.txt in this subshell though
grep -l -- "must have" *.txt
)