evita que vários canais sejam quebrados devido ao comando ausente

3

Nos scripts de shell, eu geralmente uso vários canais como este:

cmd1 | cmd2 | cmd3

Agora, se cmd2 estiver ausente, o canal resultará "quebrado" e cmd3 não receberá nenhuma entrada.

Como solução alternativa eu poderia testar explicitamente se cmd2 existe, mas isso requer alguma replicação de código que eu gostaria de evitar.

Em vez disso, eu gostaria de um teste mais conciso como este:

cmd1 | cmd2; [ $? -eq 127 ] && cat | cmd3
    
por eadmaster 03.04.2016 / 07:26

2 respostas

1

Com base no seu exemplo, parece que você está procurando uma maneira de agrupar argumentos para operações com menor precedência do que | , (por exemplo, && e || ).

Os metacaracteres { e } podem ser usados para agrupar dessa maneira.

Seu exemplo acima pode ser escrito assim (usando o status de saída de which para determinar se cmd2 existe ou não).

cmd1 | { which cmd2 >/dev/null && cmd2 || cat; } | cmd3

Por exemplo

printf "hi\n" | { : && rev || cat; } | cat

imprimirá ih

Sua sugestão de usar um subshell também funcionará, mas usa outro processo desnecessariamente

printf "hi\n" | ( : && rev || cat ) | cat

Eu diria que é provavelmente menos complicado e melhor para manutenção se você usar um if explícito fora do canal.

if [ which cmd2 >/dev/null ]
then
    cmd1 | cmd3
else
    cmd1 | cmd2 | cmd3
fi
    
por 03.04.2016 / 19:16
4

Você pode escrever uma mini função para torná-la mais concisa:

ifexists(){
    if command -v "$1"
    then "$@"
    else echo "doing cat for missing $1" >&2
         cat
    fi
}

echo hi | ifexists mycommand | cat -n
    
por 03.04.2016 / 09:22