Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Combining a redirect with a here document seems logical enough:

$ bash > foo <<EOF
echo Hello
EOF

$ less foo
Hello

But with a pipe it behaves differently:

$ bash | tee foo <<EOF
echo Hello
EOF

$ less foo
echo Hello

What's also weird is if you immediately type 'history':

$ bash | tee foo <<EOF
echo Hello
EOF
$ history
$ history
1 ...

That is, the first command still seems to be inside the newly created bash. What's going on? Why does the pipe behave differently?

share|improve this question
    
Do you claim that redirection transforms Hello to lower case hello or is that a typo? –  Hauke Laging Feb 24 at 10:44
    
Thanks, fixed.. –  Steve Bennett Feb 24 at 12:25

1 Answer 1

up vote 6 down vote accepted

You're redirecting tee's input, not bash's. Use:

bash << EOF | tee foo
echo Hello
EOF

A few more examples to illustrate how it works:

bash << EO1 3<< EO\2 | tee 3<< EO3 foo 4<< EO4
fed (as a deleted temp file open in read-only mode) to bash fd 0
EO1
fed to bash fd 3 without $variable and $(cmd) expansion
EO2
fed to tee fd 3
(not that tee does anything with its fd 3)
EO3
fed to tee fd 4
(see how, like any redirection operator 3<< END can appear anywhere on
the command line (for simple commands at least))
EO4

Redirecting compound commands:

{ head -n2; wc -l; } << EOF
fed as fd 0 for the whole command group
$(ps -e)
EOF

Or:

if head -n1; then
  head -n2
fi << EOF
1
2
3
EOF

You can reuse the same ending token:

$ ls -l /proc/self/fd << E 3<< E >&2 | 3<< E 4<< E ls -l /proc/self/fd
pipe heredoc> E
pipe heredoc> E
pipe heredoc> E
pipe heredoc> E
total 0
lr-x------ 1 stephane stephane 64 Feb 24 12:50 0 -> /tmp/zshLiVzp3 (deleted)
lrwx------ 1 stephane stephane 64 Feb 24 12:50 1 -> /dev/pts/5
lrwx------ 1 stephane stephane 64 Feb 24 12:50 2 -> /dev/pts/5
lr-x------ 1 stephane stephane 64 Feb 24 12:50 3 -> /tmp/zshFLbQ7T (deleted)
lr-x------ 1 stephane stephane 64 Feb 24 12:50 4 -> /proc/25749/fd/
total 0
lr-x------ 1 stephane stephane 64 Feb 24 12:50 0 -> pipe:[70735808]
lrwx------ 1 stephane stephane 64 Feb 24 12:50 1 -> /dev/pts/5
lrwx------ 1 stephane stephane 64 Feb 24 12:50 2 -> /dev/pts/5
lr-x------ 1 stephane stephane 64 Feb 24 12:50 3 -> /tmp/zshL3KBp3 (deleted)
lr-x------ 1 stephane stephane 64 Feb 24 12:50 4 -> /tmp/zshcJjS7T (deleted)
lr-x------ 1 stephane stephane 64 Feb 24 12:50 5 -> /proc/25748/fd/

As to why the first history command is run in that new bash in:

$ bash | tee foo <<EOF
echo Hello
EOF
$ history
$ history
1 ...

That is because bash stdin is still the terminal, but its stdout is a dead pipe (at the other end of the pipe, tee has redirected its stdin from that delete temp file, so the reading end of that pipe is closed).

bash doesn't write its prompt or the echo of what you type on its stdout (the dead pipe), but to the terminal, so that bash will let you enter history at a first prompt.

However, that history (which is a builtin, so executed by the bash process, not a child), will write its output to that dead pipe. When doing so, the bash process will receive a SIGPIPE signal (since there's no reader) and die.

The next prompt will be issued by the calling shell.

share|improve this answer
    
Ah, I see. Seems obvious now. Is there (out of curiosity) a way of using brackets or something around the first way? –  Steve Bennett Feb 24 at 12:26
1  
@SteveBennett (foo | bar)<file and {foo | bar;}<file are both possible. In that case the redirection is the input for foo, not bar. –  Hauke Laging Feb 24 at 12:30
    
Whoa, comprehensive answer, thanks very much. –  Steve Bennett Feb 24 at 12:58
    
Incidentally, do you know why you get the other behaviour: being stuck inside the subshell for one command? –  Steve Bennett Feb 25 at 1:09
    
Great answer, thanks again. –  Steve Bennett Feb 25 at 9:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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