A chave é que, sob o bash (outros shells podem diferir), um pipeline não é terminado até que todos os comandos no pipeline sejam finalizados.
Para entender, vamos considerar:
inotifywait -qm -e create . | while read line; do echo $line; break; done
Quando read
lê uma linha, é ecoada e, em seguida, break
é executado e o último processo é finalizado. O primeiro processo, no entanto, continua até que uma gravação no stdout falhe. Assim, o loop continuará pelo menos até que inotifywait
tente gravar sua linha de saída segundo . Por causa dos caprichos do buffer, isso pode não acontecer até então. Pode demorar várias linhas antes da descoberta ocorrer. Quando essa tentativa de gravação falha, o SIGPIPE é emitido.
Agora, considere o outro caso:
while read line; do echo $line; break; done < <(inotifywait -qm -e create .)
Aqui, não há pipeline. Quando break
é executado, o loop while
é concluído.
Documentação
Na seção "Pipelines" de man bash
:
The shell waits for all commands in the pipeline to terminate....
Esse comportamento é uma escolha feita por bash
. Não é obrigatório pelo POSIX. POSIX afirma:
If the pipeline is not in the background (see Asynchronous Lists), the shell shall wait for the last command specified in the pipeline to complete, and may also wait for all commands to complete.