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