The Colon in the Shell.

Mon, 08 Dec 2014 20:35:03 +0100
babble

I was recently asked about some construct in a shell script starting with a colon(:), leading me into a long monologue about it. Afterwards I realized I had forgotten to mention half of the nice things. So here for your amusement some usage for the colon in the shell:

To find the meaning of ":" in the bash manpage[1], you have to look at the start of the SHELL BUILTIN COMMANDS section. There you find:

: [arguments]
	No effect; the command does nothing beyond expanding arguments and performing any specified redirections.  A zero exit code is returned.

If you wonder what the difference to true is: I don't know any difference (except that there is no /bin/:)

So what is the colon useful for? You can use it if you need a command that does nothing, but still is a command.

For example, if you want to avoid using a negation (for fear of history expansion still being on by default on a interactive bash or wanting to support ancient shells), you cannot simply write

if conditon ; then
	# this will be an error
else
	echo condition is false
fi

but need some command there, for which the colon can be used:

if conditon ; then
	: # nothing to do in this case
else
	echo condition is false
fi

To confuse your reader, you can use the fact that the colon ignores it's arguments and you only have normal words there:

if conditon ; then
	: nothing to do in this case # <- this works but is not good style
else
	echo condition is false
fi

though I strongly recommend against it (exercise: why did I use a # there for my remark?).

This of course also works in other cases:

while processnext ; do
	:
done

The ability to ignore the actual arguments (but still processing them as with every command that ignores it arguments) can also be used, like in:

: ${VARNAME:=default}

which sets VARNAME to a default if unset or empty. (One could also use that the first time it is used, or ${VARNAME:-default} everywhere, but this can be more readable).

In other cases you do not strictly need a command, but using the colon can clear things up, like creating or truncating a file using a redirection:

: > /path/to/file

Then there is more things you can do with the colon, most I'd put under "abuse":

misuing it for comments:

: ====== here

While it has the advantage of also showing up in -x output, the to be expected confusion of the reader and the danger of using any shell active character makes this general a bad idea.

As it practically the same as true it can be used as a shorter form of true. Given that true is more readable that is a bad idea. (At least it isn't as evil as using the empty string to denote true.)

# bad style!
if condition ; then doit= ; doit2=: ; else doit=false ; doit2=false ; fi
if $doit ; then echo condition true ; fi
if $doit2 && true ; then echo condition true ; fi

Another way to scare people:

ignoreornot=
$ignoreornot echo This you can see.
ignoreornot=:
$ignoreornot echo This you cannot see.

While it works, I recommend against it: Easily confusing and any > in there or $(...) will likely rain harvoc over you.

Last and least, one can shadow the built-in colon with a different one. Only useful for obfuscation, and thus likely always evil. :(){:&:};: anyone?

This is of course not a complete list. But unless I missed something else, those are the most common cases I run into.

[1] <rant>If you never looked at it, better don't start: the bash manpage is legendary for being quite useless as hiding all information in other information in a quite absurd order. Unless you look at documentation about how to write a shell script parser, then the bash manpage is really what you want to read.</rant>