14

Can one use multiple here-docs to provide input to a command in bash?

$ cat <<<foo <<<bar
bar
$ cat <<EOF1 <<EOF2
> foo
> EOF1
> bar
> EOF2
bar

Obviously, in both cases, the second here-doc is used as stdin, and replaces the first reference. Is the solution to use echos instead?

$ cat <(echo -n foo) <(echo bar)
foobar

Also, for some reason, using a combination didn't work for me. Why would that be?

$ cat <<<foo <(echo bar)
bar
$ cat <(echo -n foo) <<<bar
foo
  • Is there any reason behind the fact that you want to use two here-documents rather than combining it into one? – beans Aug 3 '14 at 12:49
  • 1
    @beans I actually ran into it when testing out paste with dummy inputs. I suppose I can think of a few other scenarios. If I had had a script with pre-manipulated text in a few variables, then I might want to do something to both with a command that only takes files, for example diff. – Sparhawk Aug 3 '14 at 14:48
  • Another use-case (I found this using here-docs to create a shell script): you want a few lines with variable expansion and then some lines without: cat <<EOF1 <<"EOF2". – Toby Speight Jan 16 '18 at 16:41
17

You can do:

cat /dev/fd/3 3<< E1 /dev/fd/4 4<< E2
foo
E1
bar
E2

There can be only one stdin, as there's only one file descriptor 0.

cat << EOF
eof
EOF

is short for:

cat /dev/fd/0 0<< EOF
eof
EOF

And:

cat <<< foo

is:

cat /dev/fd/0 0<<< foo

You have to make up your mind what to open on file descriptor 0.

cat <(echo foo)

Is:

cat /dev/fd/123

Where 123 is a file descriptor to a pipe, and in parallel, bash runs echo foo in another process with the stdout redirected to the other end of the pipe.

Once you pass a filename to cat, cat no longer read from stdin. You'd need:

cat <(echo foo) /dev/fd/0 << EOF
bar
EOF

Or:

cat <(echo foo) - << EOF
bar
EOF

(- is to tell cat to read from stdin).

  • 1
    cat <<EOF isn't exactly the same as cat /dev/fd/0...: in the latter case cat sees the file name and does the open. – Mikel Aug 3 '14 at 16:23
  • @Mikel, what I meant is that it is functionally equivalent. When not passed any argument, cat reads from its fd 0, as if passed an argument of - or /dev/fd/0 (though on Linux (and Linux only), opening /dev/fd/0 is not exactly like duplicating the file descriptor 0). – Stéphane Chazelas Aug 3 '14 at 16:28
  • I was very surprised by /dev/fd/3 3<< E1 construct and I wonder now what exactly are items under /dev/fd/. I though they somehow appears magicaly after process opens a file somewhere on the filesystem with the exception of 1 and 2 which are there by default for every process. But in your example you are using file descriptor 3 and 4 that are not connected to any real file except for that input redirection. I can't comprehend that in my mental model of file descriptors. What if process want to open another file, would it know it has to use fd 5? Do fds have to be 3, 4, 5.. or can be anything? – calavera.info Mar 1 '18 at 8:31
  • @calavera.info, it sounds like you want to create a follow-up question. – Stéphane Chazelas Mar 1 '18 at 8:46

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.