Back Original

A shell colon does nothing. Use it anyway

A shell colon does nothing. Use it anyway.

I've written more shell scripts than I can count, but I still stumble upon tricks that honestly blow my mind far too often than I care to admit. Latest thing that blew my head clean off? The shell colon.

Published
Modified
Author
Tags

In a land far-far away..

... there was once a far too cold cup of coffee next to a freshly brewed far-too-hot one. Four different terminals where three could have been closed an hour ago, and a shell script which I really (really) did not want to write.

Who would have thought a single colon would be the one to save the day night?

Note: Want your mind blown straight away? See more colons in the limelight.

Checking for required arguments

This is a familiar dance, it's pretty much muscle memory by this point. You have a script, it takes a few arguments, and some of them are mandatory; alright, an if-statement like so many times before:

if [ -z "$1" ]; then
   echo "missing argument, aborting." 1>&2
   exit 1
fi

echo "Hello $1!"

Though.. what if I told you the above four lines could be replaced by just... one?

: "${1:?missing argument, aborting.}"
echo "Hello $1!"
$ bash example.sh
example.sh: line 1: 1: missing argument, aborting.

$ bash example.sh refp
Hello refp!

And look what happens if we refer to a variable with a proper name — it's the same behavior as previously but easier to spot; the diagnostic includes the name of our variable!

: "${GREET_NAME:?missing argument, aborting.}"
echo "Hello $GREET_NAME!"
$ bash greet.sh
greet.sh: line 1: GREET_NAME: missing argument, aborting.

Parameter expansion and the story of :?

There are two things going on in the previous snippet, and you are correct in identifying that one part is using parameter expansion:

That.. other colon

So that's one colon, but what about that other one, the one who sits alone at the beginning of the line?

More colons in the limelight

Perhaps we have already established that there is more to : than meets the eye, but to prove the real magic of the null-command — here are a few usages that blew my mind.

: "${DATA_DIR:=/var/data}"       
: "${RETRIES:=3}"                
: > error.log                    
: > error.log > access.log       
( : < dataset.json ) && echo YES 
( : >> result.json ) && echo YES 
trap : INT                       
sleep 60                         
set -u                           
: "$DEPLOY_ENV" "$HOST"          
if some-command; then
    :                            
else
    echo "command failed"
fi

Con-colon-sion

So, if you are like me and prefer less typing (gotta go fast) — the null-command and parameter expansion are a pair worth studying before your coffee goes cold.

And also.. isn't this — magic?

set  : : : : : : : : : : : : : : : : : : : : :

while : colons are more than "${1:?magic}"; do
    echo "$*" && shift
done

Note: The above example is safe to run locally, try it!

Frequently Asked Questions

After reading a few comments online, it seems I skipped over some things worth explaining. I will keep this section updated as questions come up.