1

Consider the following code:

for domain; do
    cat << EOF > "/etc/nginx/sites-available/${domain}.conf"
        My \domain is ${domain}.
    EOF
done

Note that the path /etc/nginx/sites-available/${domain}.conf is wrapped with quotation marks. Is it a best practice or done because of variable substitution? If it's variable substitution, wouldn't it be better or more common to wrap the heredoc name (EOF) instead?

1 Answers1

3

Quoting expressions which contain variables is a best-practice (as opposed to merely being a convention) in part because of variable expansion:

If the variable expands to a string which contains white-space, for example, then your code would end up writing to to wrong file. Quoting the heredoc keyword does affect variable expansion, but not in the same way that quoting affects strings:

Specifically, quoting the heredoc keyword prevents variable expansion.

And in any event, the path in question is not part of the heredoc body (which starts on the line after the first delimiter) and would therefore be unaffected - it has to be quoted independently.

Also note that (although this is unrelated to your question) the heredoc in your code snippet is invalid since the closing delimiter is indented. Consider the following excerpt from the Advanced Bash-Scripting Guide:

The closing limit string, on the final line of a here document, must start in the first character position. There can be no leading whitespace. Trailing whitespace after the limit string likewise causes unexpected behavior. The whitespace prevents the limit string from being recognized.

The exception to this is the <<- style heredocs, which ignore tab-indentation and also allow for the closing delimiter to be tab-indented. This is described in the following passage taken from the Wooledge Bash Wiki:

If you use <<-END instead of <<END as your Heredoc operator, Bash removes any tab characters in the beginning of each line of your Heredoc content before sending it to the command. That way you can still use tabs (but not spaces) to indent your Heredoc content with the rest of your code. Those tabs will not be sent to the command that receives your Heredoc. You can also use tabs to indent your sentinel string.

igal
  • 9,886
  • 1
    If tab characters only (no spaces) are used for the indentation of the heredoc terminator, and if the terminator specification begins with an additional hyphen as in cat << -EOF, then it will work correctly. I recommend avoiding tldp advanced bash guide in favor of the Wooledge Bash Wiki, which is more up to date and has better examples (without promoting bad practices as tldp often does due to its dated nature). – Wildcard Nov 09 '17 at 03:02
  • @Wildcard Thanks for the comment. I was just being lazy, I guess. I added a comment addressing this. – igal Nov 09 '17 at 03:09
  • 1
    @Wildcard: In what shell is that true? In bash and most (if not all) descendants of the Bourne shell, the - must be appended to the << redirection operator, not prepended to the terminator / delimiter word. So <<- EOF works, but << -EOF does not. – G-Man Says 'Reinstate Monica' Nov 11 '17 at 04:46
  • @G-Man I'm pretty sure that was a typo. – igal Nov 11 '17 at 04:48
  • @igal: Seriously? << -EOF could be a typo, but “if the terminator specification begins with an additional hyphen” looks like a misunderstanding. – G-Man Says 'Reinstate Monica' Nov 11 '17 at 04:54
  • @G-Man Er... just kidding? Sorry about that. The Wooledge Bash Wiki (his reference) gets it right though. I guess I didn't read his comment very carefully. – igal Nov 11 '17 at 04:58
  • @G-Man yes, thanks for pointing that out. My misunderstanding. – Wildcard Nov 11 '17 at 10:20