Introduction

Bash has a builtin command getopts for parsing parameters given as options (i.e -v, -e). getopts can only parse single character arguments that starts with -. GNU style options (i.e. –version) should be parsed manually or with other command.

Usage

getopts has the following signature:

getopts OPTSTRING VARIABLE [ARG...]

OPTSTRING is possible options as string. Each time getopts is invoked it parses an ARG character using OPTSTRING. If ARG is omitted getopts parses positional parameters (i.e. $1 - $9).

OPTSTRING accepts any uppercase, lowercase, number and most special characters as option. When it starts with colon (:), error reporting is turned off. If colon (:) is added after a option/character then that options must have value.

OPTSTRING Example:

vn - Accepts -v and -n options. -vn or -nv is also possible. If any invalid options is given prints an error message.

:vn - Accepts same options as vn, error reporting is turned off as prefixed with colon (:).

vn: - Accepts same -v option, but -n now expects value, (i.e. -n3 or -n 3 or -vn3 or -vn 3).

getopts has 3 predefined variables:

Name Description
OPTIND Index of next argument to process. It is initialized to 1 when shell starts
OPTARG If options accepts value, then its put on this variable
OPTERR Defaults to 1, stops error reporting when 0

getopts fails when all options is parsed. So its can be written with loop:

#!/bin/bash
# filename: getopts-test.sh
while getopts "vn:" NAME; do
    printf "NAME: %s, OPTIND: %d, OPTARG: %s\n" $NAME $OPTIND $OPTARG
done

# if run as ./getopts-test.sh -v -n 3
# NAME: v, OPTIND: 2, OPTARG:
# NAME: n, OPTIND: 4, OPTARG: 3

# if run as ./getopts-test.sh -vn3
# NAME: v, OPTIND: 1, OPTARG: 
# NAME: n, OPTIND: 2, OPTARG: 3

# if run as ./getopts-test.sh -zn3
# getopts-test.sh: illegal option -- z
# NAME: ?, OPTIND: 1, OPTARG: 
# NAME: n, OPTIND: 2, OPTARG: 3

When error reporting is off, invalid character is put in OPTARG and ? is put in NAME.

#!/bin/bash
# filename: getopts-test.sh
while getopts ":vn:" NAME; do
    printf "NAME: %s, OPTIND: %d, OPTARG: %s\n" $NAME $OPTIND $OPTARG
done

# if run as ./getopts-test.sh -zn3
# NAME: ?, OPTIND: 1, OPTARG: z
# NAME: n, OPTIND: 2, OPTARG: 3

Its helpful to use getopts with case statement.

#!/bin/bash
# filename: getopts-test.sh
while getopts ":vn:" NAME; do
    case "$NAME" in
        v) echo "Version 1.00" ;;
        n) echo "n:" $OPTARG ;;
        *) echo "Invalid argument";;
    esac
done

# shift parsed parameters
shift $(( OPTIND - 1 ))

# if run as ./getopts-test.sh -v -n 3 -z
# Version 1.00
# n: 3
# Invalid argument

Tools Version

  • bash 4.4.19(1)-release

Bookmarks