4

I'd have supposed this code would have printed "oof" first:

echo foo | tee >(rev) | ( sleep 1 ; cat ; )

Output:

foo
oof

Increasing the sleep time doesn't change the order. Why doesn't that work?


Note that other tools do work as supposed, e.g.: echo foo | pee rev 'sleep 1 ; cat'.

1
  • 1
    The output of rev goes through cat as well in bash (contrary to zsh) Nov 22, 2017 at 16:13

2 Answers 2

8

In

echo foo | tee >(rev) | (sleep 1; cat)

In bash like in ksh, but unlike zsh, the stdout of rev also is the pipe to (sleep 1; cat).

echo, tee, rev and the (...) subshell are started at the same time, but tee writes foo\n to stdout before the pipe to rev, so in any case, rev will write oof to the pipe after tee writes foo, so oof can only come last. Delaying cat has no incidence.

If you wanted the output of rev not to go through the pipe to (sleep 1; cat), you'd use zsh or do:

{ echo foo 3>&- | tee >(rev >&3 3>&-) 3>&- | (sleep 1; cat) 3>&-; } 3>&1

Note that zsh also has a builtin tee in its multios feature, so you can do:

echo foo > >(rev) > >(sleep 1; cat)

However in:

echo foo > >(rev) | (sleep 1; cat)

The output of rev would go through cat (confusingly considering it doesn't in the echo foo >(echo bar) | (sleep 1; cat) case).

3
  • Thanks, I needed that! For me this is one of those cases where I knew something, (prior experience juggling three or four pipelines), but failed to correlate it when needed, or perhaps hit my head somewhere...
    – agc
    Nov 22, 2017 at 16:41
  • @Stéphane, why do you close file descriptor 3 in every command? This example seems to run fine: { echo foo | tee >(rev >&3 ) | tr a-z A-Z ; } 3>&1
    – arielCo
    Dec 15, 2017 at 2:30
  • @arielCo For cleaning. They don't need that fd 3. Dec 15, 2017 at 7:19
1

Using two bash process substitutions, (instead of just one, then a pipe), then dumping the STDOUT to /dev/null, works as expected:

echo foo | tee >(rev) >( sleep 1 ; cat ; ) > /dev/null ; sleep 1

Output:

oof
foo

Notes:

  • the 2nd sleep prevents "foo" from being printed after the command prompt.
  • reducing the sleep delay number to some optimum ought to be better, but I'm not sure what that number should be. 1 is a bit slow, but always seems to work; .01 doesn't always work, (that is, the output is sometimes in the wrong order), .1 seems to work well.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .