5

I just found out about process substitution using >() and am super excited about it, however when I tried it, it doesn't always work. e.g.

This works:

cat /usr/share/dict/words |tee >(tail -1) > /dev/null
ZZZ

And this gives a broken pipe error:

cat /usr/share/dict/words |tee >(head -1) > /dev/null
1080
tee: /dev/fd/63: Broken pipe

Any idea why? Thanks!

Update: This is on RHEL 4 and RHEL 6.2

naumcho
  • 18,671
  • 14
  • 48
  • 59
  • FWIW, both of these worked for me without error (tested OS X and a Fedora-like Linux distro). – danfuzz Apr 01 '13 at 18:19
  • 1
    Try passing `-i` to `tee`: `cat /usr/share/dict/words | tee -i >(tail -1) >/dev/null` – jedwards Apr 01 '13 at 18:32
  • Same with -i: cat /usr/share/dict/words |tee -i >(head -1) > /dev/null 1080 tee: /dev/fd/63: Broken pipe – naumcho Apr 01 '13 at 18:56
  • on my OS X the `SIGPIPE` error does occur for the 'head' command. Possibly head closes the file before tee has finished writing to `/dev/null`. But that does not explain why tail does not produce an error. – suspectus Apr 01 '13 at 20:24
  • Seems like an awfully complex way to say `head -1 /usr/share/dict/words`... My guess is `head -1` exits as soon as it's read the first line, which then results in `tee` seeing a broken pipe error the next time it tries to write more out... – twalberg Apr 01 '13 at 21:27
  • @twalberg: the inspiration behind it is being able to run multiple pipes on the output of one command as suggested here: http://stackoverflow.com/questions/60942/how-can-i-send-the-stdout-of-one-process-to-multiple-processes-using-preferably/60955 – naumcho Apr 01 '13 at 22:18
  • 5
    @user779 That makes sense, but I still think the issue is the early exit of `head` - or more generally, in fact, if any of the output process pipelines exit without consuming the entire input, it will cause a write error in `tee`. You might try with `>(head -1; dd of=/dev/null)` instead, to consume the rest of the input after `head` exits. – twalberg Apr 01 '13 at 23:08
  • @twalberg gave the correct answer.. you have to read the rest of the input to keep `tee` running. A patch was suggested in May 2012 here: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=11540 to fix this behavior, but it seems to be rejected because of some issues with POSIX compliance or whatever. But normally you will end up using process substitution and reading all of the input.. You just hit kind of a bad test case to play around with 8).. – mariux Apr 02 '13 at 20:10
  • First of all, are your example commands hypothetical? What's the point of using `tee` with a single process substitution and its stdout redirected to /dev/null? You might as well just `| head -1` (recommended option is to use `head -n 1`). Having said that, `head` exits as soon as it does the job (prints one line), tee tries to write the next line to that pipe, and receives a SIGPIPE since the pipe was already closed. With GNU tee, using the `-p` option should help. – Gene Pavlovsky Feb 27 '23 at 10:59

1 Answers1

1

here's an explanation of why you get the error with head but not with tail:

head -1 only has to read one line of its input. then it will exit and the tee continues feeding its output into...

tail -1 on the other hand has to read the complete input in order to complete its job, so it will never terminate the pipe before tee is finished.

you can safely ignore the broken pipe message and many programs stopped reporting such errors. on my machine I don't see it.

user829755
  • 1,489
  • 13
  • 27