When writing a Bash script, sometimes you may want to pass arguments (or flags) to the script to drive specific behaviour. We can utilise getopts
to do this.
Let's create a simple script that will output our name. We will need to provide it forename and surname. See the usage
function which describes how we want our program to be executed.
#!/usr/bin/env bash
set -e
function usage() {
echo '
This program outputs your name
-f [forename] - your first name
-s [surname] - your last name
example: ./'$(basename "$0")' -f [forename] -s [surname]
example: ./'$(basename "$0")' -f Amit -s Dhamu
'
}
Next, we need to add something in to handle the -f
and -s
flags.
while getopts 'f:s:' flag; do
case "${flag}" in
f) FORENAME="${OPTARG}" ;;
s) SURNAME="${OPTARG}" ;;
*)
usage
exit 1
;;
esac
done
getopts
is declared here with a while
loop and f:s:
.
To explain the colons:
An option character in this string can be followed by a colon (‘:’) to indicate that it takes a required argument. If an option character is followed by two colons (‘::’), its argument is optional; this is a GNU extension.
https://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html
Then for the case
statement:
f)
- we store the contents of the supplied flag to the FORENAME
variables)
- we store the contents of the supplied flag to the SURNAME
variable*)
- handles any other flags which are not supported. If those are supplied, we issue the usage
message and exit with a non-zero exit codeLet's finish off our script by checking FORENAME
and SURNAME
are not empty. If they are, we issue the usage
message and exit with a non-zero exit code. If not, we print out a welcome message with the supplied name.
if [[ -z "${FORENAME}" || -z "${SURNAME}" ]]; then
echo "WARNING: You must supply your forename and surname"
usage
exit 1
fi
echo "Welcome ${FORENAME} ${SURNAME}"
Let's say we wanted to add in a title but didn't want to make it required. We can change our getopts
and case
statement like below.
- while getopts 'f:s:' flag; do
+ while getopts 'f:s:t::' flag; do
case "${flag}" in
f) FORENAME="${OPTARG}" ;;
s) SURNAME="${OPTARG}" ;;
+ t) TITLE="${OPTARG} " ;;
*)
usage
exit 1
;;
esac
done
Given we have a separate if
statement to validate the required arguments, we can simply change our echo
statement.
echo "Welcome ${TITLE}${FORENAME} ${SURNAME}"