I recently needed to make a set of several favicons, so I went to the web to see if anyone had a script I could borrow steal.

Sure enough, I found one written by Joshua McGee: “Create a favicon with ImageMagick” (not reproduced here for copyright reasons).

It was a simple enough script, just a series of escaped commands. I noticed, however, that it assumed a few things:

  • An image file was specified on the command line,
  • The image existed, and
  • Imagemagik was installed.

In other words, the script was not developed defensively. This makes sense: it was just a bang-out.

The script had no inline documentation, and if a favicon file that already existed in the current directory would be silently overwritten—not good.

I’m clumsy: I delete and overwrite files all the time, so I could use a little help. Maybe I can tidy up the script?

Ensure command-line parameter

Whenever your script requires a command-line parameter, display a help if it is not provided or is the wrong type. Why? Because in 6 months you will forget how to use it.

if [[ -z "$1" ]]; then
		echo -e "\nUsage:\n\t$0 image.png\n\n\tWhere 'image.png' is ..."
		exit 0
fi

Easy! The -z means “if empty”. And $1 contains the first parameter. When we display the error message, we use $0, which contains the script’s filename and path. So if I run my script like this “/foo/bar/somescript”, that is what $0 will display.

Ensure Source Image Exists

# Check to is if source file exists
if [[ ! -e $1 ]]; then
		echo -e "\nFile '$1' not found."
		exit 0
fi

I added the comment because I can never remember what “-e” means. When scanning the source, I can quickly tell what this section does without reading much further into the code.

Ask the user before overwriting

# Warn if favicon.ico already exists in current directory
if [[ -e favicon.ico ]]; then
		echo -e "Warning:\n\tfavicon.ico exists in current directory."
		choice "Overwrite? [y/N]: "
		if [ "$CHOICE" = "y" ]; then
				echo "Overwriting favicon.ico"
				rm favicon.ico
		else
				echo "Exiting"
				exit 0
		fi
fi

Another defensive-coding best-practice. Before doing anything destructive that isn’t the primary purpose of the script, let the user decide if they want to proceed. By “primary purpose” I mean that the only reason someone would run the script was to destroy something.

What’s worse is destroying something silently, which is why I let the user know when we overwrite favicon. Keeping the user informed needs to be balanced with flooding the user with too many messages.

Note that the “choice” statement above isn’t a build-in command, but a very handy one I got from O’Reilly’s “bash Cookbook”.

Is Imagemagick installed?

Actually, I don’t care because I use it so much that I always install it on whatever system I’m using. An approach I might take would be

type mogrify

And compare the result.
A good discussion of self-documenting code vs. inline documentation may be found in chapter 11 of: McConnell, Steve (2004). Code Complete (2nd ed.). Pearson Education. ISBN 9780735636972.