1

This is a question of knowledge respectively research.

I'm not quit clear why I should use this code:

cat > $FILE << EOF
command1 $var_this_routine
command2 \$var_attached_routine
...
EOF

and another time like this:

echo "command1 $var_this_routine
command2 \$var_attached_routine
...
" > $FILE

Well, what I see is a similar qoutes, but the same functionalities and results. For me, so far only looks another quotes.

To append some content I can use '>> $FILE' and it behaves the same way.

But what are the technical differences now? Which advantages or disadvantages do these variants have?

Silerra
  • 13

2 Answers2

4

Quoting, expanding variables and such

Here-document (<<) allows you to pass quotes without escaping them. It also lets you decide if certain expansions should occur in a way that doesn't interfere with quotes you need to pass.


Try:

var="12  3"
cat <<EOF
'$var"
EOF

The output is

'12  3"

To get this with echo you need one of the following:

echo "'$var"'"'
echo "'$var\""

or something similarly ugly. By looking at these commands it's hard to tell what the output should be, while the here-document it's pretty clear.


What if you don't want the variable to be expanded? You can do this:

cat <<'EOF'
'$var"
EOF

The output is literally

'$var"

Again the here-document is clear. Compare to these commands:

echo "'\$var\""
echo "'"'$var"'

In some cases you still need to escape things. e.g.

var="12  3"
cat <<EOF
We need '\$var" to be expanded and look like this: '$var"
EOF

to get

We need '$var" to be expanded and look like this: '12  3"

But with echo it's even worse:

echo "We need '\$var\" to be expanded and look like this: '$var\""
echo 'We need '"'"'$var" to be expanded and look like this: '"'$var"'"'

Could you easily predict the exact output of the last echo? Now imagine you need to add a variable to be expanded between the literal look and like. Is look like in single-quotes or in double-quotes in the already existing command?

  • if in single-quotes then the snippet should become look '"$foo"' like
  • if in double-quotes then the snippet should become look $foo like

In general there can be quotes within quotes and only the outer ones matter, so to tell which solution to use you need to parse the whole string from the beginning (or from the end), apply some heuristics or just go with trial and error.

Back to here-document. Thanks to it being clear it's easy to make changes right. echo with quoting frenzy can be so much harder to maintain.


Process flow

A here-document is processed by the shell running the script. Just after the shell sees

cat >"$file" <<EOF

it knows all the required redirections. It can read the following lines one by one and pass them to cat on the fly. I'm not saying it always does, I'm saying it's technically possible for arbitrarily long here-document.

On the other hand after the shell sees

echo "command1 $var_this_routine

it needs to read the whole multi-line string to discover the redirection at the end:

" >"$file"

Even if we started with

>"$file" echo "command1 $var_this_routine

the shell cannot be sure there are no more redirections until it gets beyond the closing ". To know what to do with the string the shell must read and memorize the whole of it.

And then it needs to pass the string to echo (or printf). In many shells echo is a builtin and it may (or may not) support very long arguments. But echo is not required to be a shell builtin, it may be a separate executable only. In such case the shell needs to pass the string to the executable and there are some limits.

So probably if anything is going to fail then it will be the echo method rather than here-document.

0

I think it goes back to the old days of bourne shell and/or csh. Back in the '90's, multi-line echoing didn't really work very well, and also you have to be careful about what you were echoing, if the content included a double-quote mark it might terminate the string earlier than wanted.

So back then we used the "<< EOF" style in shell scripts quite heavily.

Fast forward to now and some of those old shell scripts are still around, and/or you would still expect to run them, even though multi-line echoing is more robust, the shells still accept the "<< EOF" style. It does also allow you to add extra text inside the "<< EOF" section without much attention to syntax.

A_Q
  • 71