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`).