A shell colon does nothing. Use it anyway.

olexsmir1 pts0 comments

A shell colon does nothing. Use it anyway. | Filip Roséen - refp.se<br>A shell colon does nothing. Use it anyway.<br>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.

Published23 July 2026 at 03:53 UTCAuthorFilip RoséenTags#shell<br>#posix<br>#unix<br>Table of Contents<br>In a land far-far away..<br>Checking for required argumentsParameter expansion and the story of :?

That.. other colon<br>Other colons worth remembering<br>Con-colon-sion

In a land far-far away.. #

... there was once a far too cold cup of coffee next to a freshly brewed<br>far-too-hot one. Four different terminals where three could have been closed an<br>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 Other colons worth remembering.

Checking for required arguments #

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

if [ -z "$1" ]; then<br>echo "missing argument, aborting!" 1>&2<br>exit 1<br>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<br>example.sh: line 3: 1: missing argument, aborting!

$ bash example.sh refp<br>Hello refp!

Parameter expansion and the story of :? #

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

The syntax ${name:?diagnostic} checks whether $name is unset or empty<br>— if it is, the diagnostic is printed to stderr and the shell exits with a<br>non-zero status, otherwise;

if the variable is set, it is equivalent to $name.

That.. other colon #

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

: is the null command<br>— a builtin that does nothing but evaluate its arguments and discard the<br>result.

: is old — it goes all the way back to the 1971 Thompson<br>shell where it doubled as a label and Unix's very first<br>comment marker.

: two eyes staring at you in the dark, with love.

Other colons worth remembering #

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

: "${DATA_DIR:=/var/data}" # set defaults, : swallows the result<br>: "${RETRIES:=3}" # instead of running it as a command

: > error.log # truncate error.log<br>: > error.log > access.log # truncate both error.log and access.log

( : echo YES # is dataset.json readable?<br>( : >> result.json ) && echo YES # is result.json writable?

trap : INT # trap requires a command<br>sleep 60 # sleep is interruptible

set -u # error on unset variables<br>: "$DEPLOY_ENV" "$HOST" # check DEPLOY_ENV and HOST

Con-colon-sion #

So, if you are like me and prefer less typing (gotta go fast) — the null<br>command and parameter expansion are a good<br>pair to remember.

while : colons are more than punctuation; do<br>echo "I love colons"<br>sleep 1<br>done

colon shell echo colons command error

Related Articles