Multiple Option Arguments Using Getopts (Bash)

How can I take multiple arguments in bash using getopts?

Updated at suggestion of Gordon Davisson.

You need to include the ':' after both the s and e to signal that those options are expecting arguments.

#!/bin/bash

function help() {
# print the help to stderr
echo "$(basename $0) -h -s startyear -e endyear" 2>&1
exit 1
}

# Stop script if no arguments are present
if (($# == 0))
then
help
fi

while getopts 'hs:e:' OPTION; do
case "$OPTION" in
h)
help
;;
s)
startyear="$OPTARG"
;;

e)
endyear="$OPTARG"
;;
esac
done
shift "$(($OPTIND -1))"

# Checking if the startyear and endyear are 4 digits
if [[ ! ${startyear} =~ ^[0-9]{4,4}$ ]] || [[ ! ${endyear} =~ ^[0-9]{4,4}$ ]]
then
echo "Error: invalid year" 2>&1
help
fi

echo "The value provided is $startyear and $endyear"

My test run with the above.

$ ./geto -s 2018 -e 2020
The value provided is 2018
The value provided is 2020
The value provided is 2018 and 2020
$

Bash getopt to accept multiple parameters

First, you have a typo: OPTORG should be OPTARG.

More importantly, you don't need the calls to shift. getopts takes care of consuming and skipping over each option and argument.

while getopts "f:l:" option; do
case "${option}" in
f) firstdate=${OPTARG} ;;
l) lastdate=${OPTARG} ;;
*)
echo "UsageInfo"
exit 1
;;
esac
done

getopts to get multiple values for same argument

You can achieve the effect by repeating -c :

declare -a cmds
id="rm08397"
while getopts ":c:f:" opt
do
case $opt in
f ) file="$OPTARG";;
c ) cmds+=("$OPTARG");;
esac
done
shift $((OPTIND -1))

for host in $(<$file);do
for cmd in "${cmds[@]}";do
echo ssh "$id@$host" "$cmd"
done
done

# Usage: ./ssh.sh -f file_of_hosts.txt -c "Command1" -c "command2"

how to handle bash with multiple arguments for multiple options

Could something like this work for you?

#!/bin/bash

while getopts ":a:p:" opt; do
case $opt in
a) arg1="$OPTARG"
;;
p) arg2="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" >&2
;;
esac
done

printf "Argument 1 is %s\n" "$arg1"
printf "Argument 2 is %s\n" "$arg2"

You can then call your script like this:

./script.sh -p 'world' -a 'hello'

The output for the above will be:

Argument 1 is hello
Argument 2 is world

Update

You can use the same option multiple times. When parsing the argument values, you can then add them to an array.

#!/bin/bash

while getopts "c:" opt; do
case $opt in
c) currs+=("$OPTARG");;
#...
esac
done
shift $((OPTIND -1))

for cur in "${currs[@]}"; do
echo "$cur"
done

You can then call your script as follows:

./script.sh -c USD -c CAD

The output will be:

USD
CAD

Reference: BASH: getopts retrieving multiple variables from one flag

bash getopts with multiple and mandatory options

You can concatenate the options you provide and getopts will separate them. In your case statement you will handle each option individually.

You can set a flag when options are seen and check to make sure mandatory "options" (!) are present after the getopts loop has completed.

Here is an example:

#!/bin/bash
rflag=false
small_r=false
big_r=false

usage () { echo "How to use"; }

options=':ij:rRvhm'
while getopts $options option
do
case "$option" in
i ) i_func;;
j ) j_arg=$OPTARG;;
r ) rflag=true; small_r=true;;
R ) rflag=true; big_r=true;;
v ) v_func; other_func;;
h ) usage; exit;;
\? ) echo "Unknown option: -$OPTARG" >&2; exit 1;;
: ) echo "Missing option argument for -$OPTARG" >&2; exit 1;;
* ) echo "Unimplemented option: -$option" >&2; exit 1;;
esac
done

if ((OPTIND == 1))
then
echo "No options specified"
fi

shift $((OPTIND - 1))

if (($# == 0))
then
echo "No positional arguments specified"
fi

if ! $rflag && [[ -d $1 ]]
then
echo "-r or -R must be included when a directory is specified" >&2
exit 1
fi

This represents a complete reference implementation of a getopts function, but is only a sketch of a larger script.



Related Topics



Leave a reply



Submit