No Bash, você pode usar substituição de processos com tee:
tee >(grep XXX > err.log) | grep -v XXX > all.log
Isso colocará todas as linhas correspondentes a XXX em err.log e todas as linhas em all.log . >( ... ) cria o processo entre parênteses e conecta sua saída padrão a um pipe. Isso funciona em zsh e em outros shells modernos também.
Você também pode usar o comando pee de moreutils :
pee "grep XXX > err.log" "grep -v XXX > all.log"
pee redireciona a entrada padrão para vários comandos ("tee para pipes").
Outra alternativa é com o awk:
awk '{ if (/^([0-9]{1,3}\.){3}[0-9]{1,3}/) { print > "err.log" } else { print > "all.log" } }'
Isso testa todas as linhas em relação à expressão e grava tudo em err.log se corresponder e all.log se não corresponder.
A expressão regular awk também é adequada para grep -E (embora corresponda alguns endereços incorretos - 999.0.0.0 e assim por diante - mas isso provavelmente não é um problema).