Em
cmd1 | cmd2
cmd1
e cmd2
são iniciados em paralelo com o stdout de cmd1
conectado à extremidade de gravação de um pipe (ou socketpair em ksh93), e o stdin de cmd2
conectado à outra extremidade desse tubo.
Em:
cmd < file
cmd
é iniciado com o stdin de cmd
aberto no file
.
Então você pode ver que
cmd1 | cmd2 < file
conflitos; você tem que escolher se o stdin de cmd2
é o canal de cmd1
ou o file
.
Acima, na maioria dos shells, o <file
tem precedência quando o redirecionamento é feito após (o shell inicia 2 processos com o pipe entre eles, e então interpreta cada um dos comandos, incluindo redirecionamentos dentro de cada um deles de forma independente)
Isso significa que o stdin de cmd2
será file
e o canal echo
que está gravando não terá leitor (um canal quebrado). Portanto, no seu caso, bar
nunca chegará a nc
e o processo que estiver executando echo bar
poderá até ser morto se gravar bar
depois que o outro processo abrir o arquivo.
Em zsh
, no entanto, com a opção multios
ativada (e ativada por padrão), zsh
detecta que você está tentando redirecionar o mesmo descritor de arquivo (aqui 0, stdin) duas vezes e o leva que você queria que os dados de ambas as fontes fossem enviados para cmd2
, então, em vez de tornar cmd2
'stdin the pipe' de cmd1
ou file
, ele realmente iniciará um alimentador <cmd2
.
cmd1 < <(cmd2)
é apenas um caso de cmd1 < file
onde file
é um pipe nomeado (ou algo que se comporta como um pipe nomeado) com cmd2
escrito na outra extremidade, mas de outra forma não é muito diferente.
Portavelmente, se você quiser enviar a saída de dois comandos, ou enviar a saída de um comando e o conteúdo de um arquivo para algum comando, você usaria:
{
cmd1
cmd2
} | cmd3
Ou:
{
cmd1
cat < file
} | cmd2
Então, aqui:
{
echo bar
echo foo
} | nc localhost 6969