Para um pipe, o final do arquivo é visto pelo consumidor (s) assim que todos os produtores tiverem fechado o descritor de arquivo para o canal e o consumidor tiver lido todos os dados.
Então, em:
{
echo foo
echo bar
} | cat
cat
verá o fim do arquivo assim que o segundo echo
terminar e cat
ler foo\n
e bar\n
. Não há mais nada para você fazer.
É importante ter em mente que, se alguns dos comandos do lado esquerdo do pipe iniciarem algum processo em segundo plano, esse processo em segundo plano herdará um fd no canal (seu stdout), portanto cat
não verá eof até que esse processo também morra ou feche sua stdout. Como em:
{
echo foo
sleep 10 &
echo bar
} | cat
Você vê cat
não retornar antes de 10 segundos se passarem.
Aqui, você pode querer redirecionar o stdout de sleep
para algo como /dev/null
se não quiser que sua (não) saída seja alimentada para cat
:
{
echo foo
sleep 10 > /dev/null &
echo bar
} | cat
Se você quiser que a extremidade de gravação do canal seja fechada antes que o último comando na subcamada à esquerda do |
seja executado, é possível fechar o stdout ou redirecionar para essa sub-rede no meio do subshell com exec
como:
{
echo foo
exec > /dev/null
sleep 10
} | (cat; echo "cat is now gone")
No entanto, observe que a maioria das shells ainda aguardará essa subshell, além do comando cat
. Então, enquanto você verá cat is now gone
imediatamente (após foo
ser lido), você ainda terá que esperar 10 segundos para que todo o pipeline seja concluído. Claro, nesse exemplo acima, faria mais sentido escrevê-lo:
echo foo | cat
sleep 10
<<ANYTHING...content...ANYTHING
é um documento aqui, é para tornar o stdin de comando um arquivo que contém o conteúdo . Não seria útil lá. é um byte que, quando lido de um terminal, faz com que os dados mantidos por um dispositivo terminal sejam liberados para a leitura do aplicativo (e quando não há dados,
read()
retorna 0, o que significa fim de arquivo). Mais uma vez, não é de nenhuma utilidade aqui.