How to easily create bash scripts that support options
Leverage the built-in getopt shell routine to create easy to use and extend Bash scripts that support options like many Linux command line utilities.

Table of contents
Sample script
Lets say we want to create a bash script called archive-project.sh
to archive a Gitlab project repository. Here is how we want the script to be usable :
(bash)$ ./archive-project.sh -h
Archive Gitlab project repository
Usage :
> ./archive-project.sh --id <project-id> -u <gitlab-url> --token <gitlab-token>
Options :
-h, --help Show help on how to use this script
--id ID of the project to archive
-u, --url URL of the Gitlab instance where the project resides
-t, --token User API token to use for authentication.
The user generating the API token need to have
'Owner' privilege on the project to archive
As you can see, the script users will be able to set options to tell the script which project to archive, on which Gitlab instance, using which authentication token. getopt
can be very useful in achiving that. We will see how, keep reading 😉
Benefits of using getopt
The getopt
shell routine can be very useful to create shell scripts that support options. getopt
will take care of the following for you :
- check and validate your predefined options
- recognize your short (
-s
for instance), long (--my-long-option
) or alternate (-myoption
) options - check and validate options arguments when required
- exit with error code different from 0 when something goes wrong (required option argument not set, undefined options passed to the script...)
- print precise error messages (in your locales configured language)
- ability to disable error message printing in order to print your custom messages
How getopt works ?
When using getopt
, two parts separated by --
can be identified. The first part is where we customize getopt
behavior by using some of its options to tell which predefined options we want our scripts to support, on which form we want them to be (long: --something
, short: -b
...), do they have required parameters, and so on.
The second part is the script arguments array that getopt
will parse to recognize our predefined options and do some treatments. That second part is generally retrieved inside bash scripts with "$@"
variable, which stores the bash script arguments.
Here is the getopt
command line to use inside the archive-project.sh
sample script :
getopt -s 'bash' -o 'h,u,t' -a -l 'help,id:,url:,token:' -n 'archive-project.sh' -- "$@"
In the above getopt
command, we used the following options :
--name, -n
: the name of the script that will be used bygetopt
when reporting some errors... for instance, when detecting unrecognized options in bash scripts arguments.
Ex : archive-project.sh : unrecognize option '--fakeoption'--shell, -s
: represents the type of shell we will usegetopt
in for parsing scripts arguments... can bebash
ortcsh
--longoptions, -l
: tellgetopt
to recognize the comma separated long options we specified... the:
at the end of each option tellgetopt
that arguments are required for those options. We can also use::
instead to tellgetopt
that we want argument to be optional for a specific options.-a, --alternative
: allow long options to start with a single-
. This means that using-token
for instance when using the script will also work in addition to--token
. When parsing the script args, you have to use the long options form (--token
) in thewhile/case
loop...-token
won't be recognize...-o, --options
: short options
We can also use -q
option in the preceding getopt
command line if we don't want to print built-in error messages. Not using the -q
option makes getopt
prints error messages when users :
- call the script with an undefined option
- call the script with a defined option but whitout argument, when one is required
- for an error related to
getopt
itself
Example error messages
(bash)$ ./archive-project.sh --id
archive-project.sh: option '--id' requires an argument
(bash)$ ./archive-project.sh --non-existent-option
archive-project.sh: unrecognized option '--non-existent-option'
Using getopt to implement the sample script
In this section we will demonstrate how to implement the behavior defined for the archive-project.sh
script and see in practice, how user friendly scripts that are easily configurable and extendable could be built by leveraging getopt
features.
As a reminder, here is how we want the script to be usable :
(bash)$ ./archive-project.sh -h
Archive Gitlab project repository
Usage :
> ./archive-project.sh -id <project-id> -u <gitlab-url> --token <access-token>
Options :
-h, --help Show help on how to use this script
-id, --project-id ID of the project to archive
-u, --gitlab-url URL of the Gitlab instance where the project resides
-t, --access-token User API token to use for authentication.
The user generating the API token need to have
'Owner' privilege on the project to archive
As you can see, it is easily configurable thanks to options. Adding new features simply means new options for users, which is very user friendly.
In the first part of the script we define functions :
#!/bin/bash
# Print usage
usage() {
echo -e "\nArchive Gitlab project repository \n"
echo -e "Usage : $0 -id <project-id> -u <gitlab-url> --token <access-token> \n"
echo -e "Options : \n"
echo -e "-h, --help \t Show help on how to use this script"
echo -e "-id, --project-id \t ID of the project to archive"
(...)
exit 1
}
# Archive project
archive_project()
{
gitlab_url=$1 # value taken from the first argument of the function
project_id=$2 # value taken from the second argument of the function
access_token=$3 # value taken from the third argument of the function
# code to archive Gitlab project here
}
The usage
function will be called when the script is run whithout arguments or with the -h
option. The archive_project
function will be called when users properly set each of the options required to archive a Gitlab project.
Here is the remaining part of the archive-project.sh
script devided into multiple pieces :
Piece #1
# getopt command used to add option support
GETOPT=$(getopt -s 'bash' -o 'h,u:,t:' -a -l 'help,id:,url:,token:' -n 'archive-project.sh' -- "$@")
# If there is any error with the previous getopt command,
# an explicit error message will be printed by getopt and
# the script will exit
if [ $? -ne 0 ]; then
exit 1
fi
# If no argument is provided print usage and exit
if [[ -z "$@" ]] ; then usage ; exit 1 ; fi
Piece #2
eval set -- "$GETOPT"
- Sets the value of positional arguments (
$@
) to the value ofGETOPT
variable - This is done only when the
getopt
command in Piece #1 succeeds - The
GETOPT
variable will simply contain all arguments passed to the script plus the--
at the end. Example :
# Script execution command
(bash)# ./archive-project.sh -id 152 --gitlab-url https://gitlab.hackerstack.org --access-token mytoken
# GETOPT variable resulting content
-id '152' --gitlab-url 'https://gitlab.hackerstack.org' --access-token 'mytoken
Piece #3
while true; do
case "$1" in
-h|--help)
usage
;;
--id)
id=$2
shift 2;
;;
-u|--gitlab-url)
url=$2
shift 2;
;;
-t|--access-token)
token=$2
shift 2;
;;
--)
shift ;
break ;
;;
esac
done
# Exploit parsed options arguments to archive the Gitlab project
archive_project $url $id $token
- Retrives options arguments from positional arguments (contained in
$@
) thanks to awhile/case
loop. - For each valid option present in the script arguments, do something. For the
-h
or--help
options for instance, call theusage
function - For each of the others options, set their arguments values to a new variable and move to the next option in the positional argument (
shift 2
) - We are at the end of the positional arguments when the
--
argument is retrieved. It's time to exit the loop (shift
+break
) and exploit the saved options values - The users inputs required to archive a Gitlab project, passed through the corresponding options are now saved in the
url
,id
andtoken
variables and can be passed to thearchive_project
function to archive the corresponding project
And voilà ! Now you know how to build bash utilities that are user friendly, configurable and easily extendable thanks to flags support added with getopt