0

I want to do something like this:

echo 'foo' | tee /dev/stdout > >(cat)

where the stdout from echo gets sent to the terminal and to the cat process. Is there a simpler way to do this?

When I run this:

 echo 'foo' | tee >(echo 'bar')

for some reason, it does not echo 'foo' it only echoes 'bar', why?

8
  • echo 'foo' | tee >(echo 'bar') prints bar and foo for me. Sep 18 '19 at 20:56
  • that's so weird b/c it doesn't for me, I am on MacOS, maybe tee is different here Sep 18 '19 at 20:58
  • 3
    @KamilMaciorowski It's absolutely pointless to argue about that; it's all about the order in which the echo foo, echo bar and tee commands will be started and finished, and that's unpredictable. If echo bar finishes before tee tries to write anything into its pipe, tee will be killed by a SIGPIPE. Sep 18 '19 at 21:10
  • 2
    You do it exactly the way that you have shown, but the command in the process substitution should read what's written to it, or it may terminate too early.
    – Kusalananda
    Sep 18 '19 at 21:16
  • 1
    echo foo | tee >(echo bar; cat >/dev/null) in your second example Sep 18 '19 at 21:21
4

You do it exactly the way you have shown:

somecommand | tee >(othercommand)

The output of somecommand would be written to the input of othercommand and to standard output.

The issue with your echo 'bar' process substitution is that it doesn't care about the input that comes via tee from echo 'foo', so it just outputs bar as quickly as it can and terminates. The tee utility then tries to write to it, but fails and therefore terminates (from receiving a PIPE signal) before it writes the string to standard output. Or, tee may have time to write the data to the process substitution, in which case both bar and foo would be printed on standard output, it's not deterministic.

You need to make sure that the command in the process substitution actually reads the data sent to it (otherwise, what would be the point of sending it data?) As Uncle Billy suggests in comments, this is easily arranged in your example by letting the process substitution simply use cat >/dev/null (assuming you're not interested in the data coming from tee):

echo 'foo' | tee >(cat >/dev/null; echo 'bar')

or

echo 'foo' | tee >(echo 'bar'; cat >/dev/null)

(these two variations would vary only in the order of the final output of the two strings)

1
  • somecommand | tee >(othercommand); cmd3 is problematic in several shell implementations including bash in that othercommand is not waited for, so its output may come after the output of cmd3 for instance. { cmd1 3>&- | tee /dev/fd/4 4>&1 >&3 3>&- | cmd2 3>&-; } 3>&1 would not have the problem and would work with POSIX sh on systems with /dev/fd/x Oct 2 '19 at 9:21
-1
echo 'foo' | tee /dev/tty |other-program
5
  • 1
    That would not really put foo on standard output though.
    – Kusalananda
    Sep 18 '19 at 21:38
  • yeah and not always looking for /dev/tty, just to stdout, whatever it may be Sep 18 '19 at 21:40
  • It does. Test it: echo 'foo' | tee /dev/tty |wc
    – bitinerant
    Sep 18 '19 at 21:40
  • Try putting your command in a script,  and then running the script with stdout redirected. Sep 19 '19 at 0:01
  • Sorry - I misunderstood the OP.
    – bitinerant
    Sep 19 '19 at 6:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.