Skip to main content

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