Sample Bash script for parsing and dealing with command options using getopt.
--- title: How To Parse In Bash Using getopt author: Bahman Movaqar date: Mar 13, 2015 source: http://www.bahmanm.com/blogs/command-line-options-how-to-parse-in-bash-using-getopt --- ## Introduction Most of the times, when you need to automate system administration tasks on your Linux machine, writing a Bash script is your best bet. And sometimes, you need to be able to control the behaviour of your script at some point which leaves you with two choices: use environment variables (set before running the script) as sort of a flag or the better and more intuitive way to use command line arguments. ## What is "getopt"? `getopt` is a program that parses command line options in shell scripts. It is the enhanced version of older `getopts` and uses the `getopt` C library to do its job. It is compatible with `getopts` as long as `GETOPT_COMPATIBLE` environment variable is set, however some of it best features are not available in compatibility mode. ## An overview of command options Command line input is viewed in 3 categories by `getopt`: short options (like `-a`), long options (like `--some-option`) and non-option parameters (like `/home/bahman/reports.txt`). Also short and long options can accept arguments (like `-a /home/bahman/Temp` or `--some-option 'A commit comment'`). ### Short option A short option is composed of a `-` (_dash_ character) followed by a single letter, for example `-a` or `-A`, and it may expect an argument. * Without argument like `-a` or `-H` * With argument * With required arguments like `-a bahman `or `-H reports` * With optional arguments like `-abahman`. _Note that there can't be any spaces between the option (`-a`) and the argument (`bahman`)._ ### Long option A long option is composed of a `--` (two consequent _dash_ characters) followed by any number of alpha-numeric characters (like `--option-a`) and it may expect an argument. * Without argument like `--option-a` or `--more-2-go` * With arguments * With required arguments like `--file-to-process reports` or `--package-name-prefix='com.bahmanm'` * With optional arguments like `--package-name-prefix='com.bahmanm'`. _Note that the argument can be passed only using `=`._ ## What is an "option string"? The only way to tell `getopt` about the options it should expect is by building an option string. Normally you would pass 2 option strings to `getopt`, one for short options and the other for long options. ### Option string for short options It is passed to `getopt` using `-o` option and follows the rules below. **Rules**: 1. Each single character stands for an option. 2. A `:` (_colon_ character) tells that the option has a required argument. 3. A `::` (two consequent _colon_ character) tells that the option has an optional argument. **Example**: The option string `f:gh::i:` means that the are four options. `f` has a required argument, `g` has no argument, `h` has an optional argument and `i` has a required argument. ### Option string for long options It is passed to `getopt` using `--long` option and follows the rules below. **Rules**: 1. Options are separated by `,` (_comma_ character). 2. A `:` (_colon_ character) tells that the option has a required argument. 3. A `::` (two consequent _colon_ character) tells that the option has an optional argument. **Example**: The options string `foo,bar::,baz:,foobar` means that there are four options. `foo` has no argument, `bar` has an optional argument, `baz` has a required argument and `foobar` has no argument. ## Show me some real code! Here's a sample Bash script parsing and dealing with options --I hope I've put enough comments in. ```bash #!/bin/bash # “a” and “arga” have optional arguments with default values. # “b” and “argb” have no arguments, acting as sort of a flag. # “c” and “argc” have required arguments. # set an initial value for the flag ARG_B=0 # read the options TEMP=`getopt -o a::bc: --long arga::,argb,argc: -n 'test.sh' -- "$@"` eval set -- "$TEMP" # extract options and their arguments into variables. while true ; do case "$1" in -a|--arga) case "$2" in "") ARG_A='some default value' ; shift 2 ;; *) ARG_A=$2 ; shift 2 ;; esac ;; -b|--argb) ARG_B=1 ; shift ;; -c|--argc) case "$2" in "") shift 2 ;; *) ARG_C=$2 ; shift 2 ;; esac ;; --) shift ; break ;; *) echo "Internal error!" ; exit 1 ;; esac done # do something with the variables -- in this case the lamest possible one :-) echo "ARG_A = $ARG_A" echo "ARG_B = $ARG_B" echo "ARG_C = $ARG_C" ``` ## Conclusion You can use `getopt` to professionally deal with command options in a civilised manner in your Bash scripts. No need for dirty tricks. Don't forget to read the `getopt` manpage. There's still some minor topics I haven't covered here, like testing for getopt's existence (`-T`).