Table of Contents
Here's my five penn'orth. A bash script (actually any program!!) should:
Use getopt(1) to process command line arguments. There are many good reasons for this. Just do it. Let me count (some of) the ways:
- provides a rational, predictable user interface - compare the nasty old peculiarities of tar and find!!
- supports short option merging eg
foobar -s -f -t == foobar -sft
- disambiguates option argument spacing eg foobar -z1 == foobar -z 1
- re-orders options so they can be processed and then popped and forgotten
–to terminate options
- plain old simple works - why write bug-prone new code when getopt(1) just works?
Even better, use my getopt(1) wrapper 2-argp.sh which is kinda sorta like GNU's argp(3) in glibc. It gives you a single place to define options which is then used to:
- create the getopt(1) command line,
- process the options setting appropriate environment parameters
- print help & man pages without any extra code
- honours GNU's ARGP_HELP_FMT environment variable
- is pretty similar to GNU's argp(3) which is a getopt(3) wrapper in glibc
- further reduces the chance of bugs arising - particularly as the script is maintained
- increase the chance that help and man pages are actually written
Support Long options
Always provide long options as well as single letter options - they're more mnemonic for infrequent users and provide valuable documentation when scripted.
respond to the -h, –help option with a usage message to !!!STDOUT!!! and exit 0. This help should be available no matter what the machine's state - so issue it before looking for dependencies and without making assumptions about what is installed.
If there are specific dependencies, then make sure they are documented in the help message.
Provide version info
provide a way to get the program's version eg -V, –version to !!!STDOUT!!! and exit 0
Note that -h and -V processing should happen before any other substantial processing or checking is done - make sure -h can always be done no matter what
Be disciplined with error messages
Error messages should go to !!!STDERR!!! - do not print the usage as it just fills the screen and hides the meat of the error. At the most, refer the user to the usage page with
run 'foobar -h' for help or 'man foobar' for a reference manual.
Be disciplined with error exit codes
non-zero exit on any error
Silence is golden
execute as silently as possible so the user doesn't have to scour through copious output. If feedback on progress is needed, just “echo -n .”
The exception, of course, is if a verbosity command is given, generally with -v, –verbose - and the output goes to stdout, thank you very much (so we can distinguish bash's own -x output which goes to stderr)
include a man page if non-trivial
Use a crunchbang
always include the crunchbang as the first line:
#! /usr/bin/env bash
Structure the code
use subroutines heavily - only put the following in the mainline:
initialise process_options "$@" main "$@"