J'ai observé le comportement suivant dans bash:
{ echo 'foo' ; sleep 10 ; }
-> sortie standard "foo" apparaît immédiatement, après 10 secondes la command est terminée (comme prévu)
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo')
-> sortie standard "foo" apparaît immédiatement, après 10 secondes la command est terminée (comme prévu)
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' | grep 'oo')
-> sortie standard "foo" apparaît après 10 secondes
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' >&2)
-> erreur standard "foo" apparaît après 10 secondes
Pourquoi la command line avec le seul grep dans la substitution de command affiche-t-elle son résultat immédiatement alors que les variantes avec le canal et la redirection attendent la fin du sumil?
Vous n'avez pas besoin d'avoir autant de fantaisie; vous pouvez observer le même effet avec
{ echo 'foo' ; sleep 10 ; } | grep oo | grep oo
ou
{ echo 'foo' ; sleep 10 ; } | grep oo | cat
ou
/tmp
). { echo 'foo' ; sleep 10 ; } | grep oo > foo.out
{ echo 'foo' ; sleep 10 ; } | grep oo > foo.out
{ echo 'foo' ; sleep 10 ; } | grep oo > foo.out
. ls -ld foo.out
plusieurs fois. foo.out
apparaît immédiatement, mais qu'il est de taille 0 pendant dix secondes, après quoi il devient 4 octets. Simplement: les tests grep
pour voir si sa sortie (standard) est un terminal. Si c'est le cas, il écrit la sortie aussi rapidement que la sortie à écrire. Si ce n'est pas le cas, il tamponne sa sortie et écrit N octets à la fois, où N est typiquement 512, mais peut être différent dans certaines implémentations.
Extension de la réponse de Scott:
Comparer
{ echo 'foo' ; sleep 3 ; } | grep oo | cat
avec
{ echo 'foo' ; sleep 3 ; } | stdbuf -o 0 grep oo | cat