=====Unixscripts:Decent Bash===== Here's my five penn'orth. A bash script (actually any program!!) should: ====Use getopt(1)==== 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 * supports ''--'' to terminate options * plain old simple works - why write bug-prone new code when **getopt**(1) just works? ====Use argp.sh(1)==== Even better, use my **getopt**(1) wrapper [[unixscripts: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 [[http://www.gnu.org/software/libtool/manual/libc/Argp-User-Customization.html | 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. ====Provide help==== 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) ====man(1) page==== 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 "$@"