Bash Shell – Multi-Line Command with Comments

bashshell

Consider

echo \ # this is a comment
foo

This gives:

$ sh foo.sh
 # this is a comment
foo.sh: line 2: foo: command not found

After some searching on the web, I found a solution by DigitalRoss on sister site Stack Overflow. So one can do

echo `: this is a comment` \
foo

or alternatively

echo $(: this is a comment) \
foo

However, DigitalRoss didn't explain why these solutions work. I'd appreciate an explanation. He replied with a comment:

There used to be a shell goto command which branched to labels
specified like : here. The goto is gone but you can still use the
: whatever syntax … : is a sort of parsed comment now.

But I'd like more details and context, including a discussion of portability.

Of course, if anyone has other solutions, that would be good too.

See also the earlier question How to comment multi-line commands in shell scripts?.


Take home message from the discussion below.
The `: this is a comment` is just a command substitution.
The output of : this is a comment is nothing, and that
gets put in the place of `: this is a comment`.

A better choice is the following:

echo `# this is a comment` \
foo

Best Answer

Comments end at the first newline (see shell token recognition rule 10), without allowing continuation lines, so this code has foo in a separate command line:

echo # this is a comment \
foo

As for your first proposal, the backslash isn't followed by a newline, you're just quoting the space: it's equivalent to

echo ' # this is a comment'
foo

$(: this is a comment) substitutes the output of the command : this is a comment. If the output of that command is empty, this is effectively a highly confusing way to insert a comment in the middle of a line.

There's no magic going on: : is an ordinary command, the colon utility, which does nothing. The colon utility is mostly useful when the shell syntax requires a command but you happen to have nothing to do.

# Sample code to compress files that don't look compressed
case "$1" in
  *.gz|*.tgz|*.bz2|*.zip|*.jar|*.od?) :;; # the file is already compressed
  *) bzip2 -9 "$1";;
esac

Another use case is an idiom for setting a variable if it's not already set.

: "${foo:=default value}"

The remark about goto is a historical one. The colon utility dates back from even before the Bourne shell, all the way to the Thompson shell, which had a goto instruction. The colon then meant a label; a colon is a fairly common syntax for goto labels (it's still present in sed).