Multiline shell script comments - how does this work?
That is not a multi-line comment. #
is a single line comment.
:
(colon) is not a comment at all, but rather a shell built-in command that is basically a NOP, a null operation that does nothing except return true, like true
(and thus setting $?
to 0 as a side effect). However since it is a command, it can accept arguments, and since it ignores its arguments, in most cases it superficially acts like a comment. The main problem with this kludge is the arguments are still expanded, leading to a host of unintended consequences. The arguments are still affected by syntax errors, redirections are still performed so : > file
will truncate file
, and : $(dangerous command)
substitutions will still run.
The least surprising completely safe way to insert comments in shell scripts is with #
. Stick to that even for multi-line comments. Never attempt to (ab)use :
for comments. There is no dedicated multi-line comment mechanism in shell that is analogous to the slash-star /* */
form in C
-like languages.
For the sake of completeness, but not because it is recommended practice, I will mention that it is possible to use here-documents to do multi-line "comments":
: <<'end_long_comment'
This is an abuse of the null command ':' and the here-document syntax
to achieve a "multi-line comment". According to the POSIX spec linked
above, if any character in the delimiter word ("end_long_comment" in
this case) above is quoted, the here-document will not be expanded in
any way. This is **critical**, as failing to quote the "end_long_comment"
will result in the problems with unintended expansions described above.
All of this text in this here-doc goes to the standard input of :, which
does nothing with it, hence the effect is like a comment. There is very
little point to doing this besides throwing people off. Just use '#'.
end_long_comment
It's not any style of commenting. the :
built-in command does absolutely nothing; it's being abused for commenting here.
$ help :
:: :
Null command.
No effect; the command does nothing.
Exit Status:
Always succeeds.
In early shells, the colon was the only way to create comments.
However, it is not a true comment, because the line is parsed in exactly the same way as any other command is parsed, and that may have side effects. For example:
: ${a:=x} # assigns the value 'x' to the variable, 'a'
: $(command) # executes 'command'
(Sometimes the colon is use solely for the purpose of invoking those side effects, but then it’s not being used as a comment.)
It is sometimes convenient to use the colon to comment out a section of a script:
: '
while [ "$n" -ne "$x" ]
do
: whatever
done
'
This is a great timesaver over preceding each line with #
, particularly if the
commenting out is only temporary.