How not to program Bash

Came across this gem today:

COMP=$1

if [ -e $COMP ]; then
    echo "Please supply a competition_id"
    exit
fi

On first read it looks backwards – “if exist $COMP then exit”, and the programmer clearly wanted to do the exact opposite. However it actually works as desired. Mostly.

If no argument is supplied, $COMP will be a blank string, i.e. “”. Thus [ -e $COMP ] will parse to [ -e ], which returns 0 (effectively true). It’s basically like saying “does nothing exist”.

This is because the -e argument tests whether a file exists. So if an argument is supplied, [ -e $COMP ] will return 1 (effectively false), which does what the programmer intended UNLESS the argument supplied is a valid file path.

In this case a number was expected, so sure it’s unlikely to fail in this way, but it’s still an incredibly bad way to test if an argument is set. Not to mention confusing to read!

The correct way to test this by the way would be to use -z, which simply tests if a string’s length is zero:

COMP=$1

if [ -z "$COMP" ]; then
    echo "Please supply a competition id"
    exit
fi

Or better still, use getopts. For more info run ‘man test’ from a bash terminal.

Leave a Reply