I want to run the script as ./script speed -a some_value -b some_value
also ./script accuracy -a some_value -b some_value
What I tried is
while [ -n "$1" ]; do
case "$1" in
speed)
for i in "${@:2}"
do while getopts "a:b:" opt; do
case "${opt}" in
a) list=$OPTARG
echo $list
;;
b) list2=$OPTARG
echo $list2
;;
esac
done
done
echo "speed option passed"
break ;;
accuracy) echo "similar to above function"
break ;;
*) echo "Option $1 not recognized" ;; # In case you typed a different option other than a,b,c
esac
shift
done
getting output as when ran ./script speed -a some_value
this is something
speed option passed
I don't know if this is possible or not or is there any way to do something like this?
I don't think you want the outer loop (while [ -n "$1" ]; do
), unless you want to be able to process multiple subcommands in a single run. That is, do you want this:
./script speed -a some_value -b some_value accuracy -a some_value -b some_value
To be roughly equivalent to this:
./script speed -a some_value -b some_value
./script accuracy -a some_value -b some_value
If not, remove that loop because you'll only be processing one subcommand per run. If you do want to process more than one subcommand per run, then you need to take some extra steps to remove or skip over the arguments relating to one subcommand before running the next one.
You do want to remove the for i in "${@:2}"
loop -- that just doesn't mix with the way getopts
works. What you do need to do is skip over the subcommand name before processing the options. You could either use shift
to remove the subcommand name, something like this:
case "$1" in
speed)
shift # Remove the first argument ("speed")
while getopts "a:b:" opt; do
...
If you're going to allow multiple subcommands, add shift $((OPTIND-1))
sfter the getopts
loop, to get it ready for the next subcommand.
Or you could modify OPTIND
to tell getopts
that it's already processed the first argument and it can go to work on the second:
case "$1" in
speed)
OPTIND=2 # Tell getopts to start processing at arg #2
while getopts "a:b:" opt; do
...
If you're going to handle multiple subcommands with this method... well, it's a bit more complicated and I think I'll duck the question.
Yet another option is to put the code for each subcommand in a function, and call it with all but the first argument:
speed_subcommand() {
local OPTIND
while getopts "a:b:" opt; do
...
}
case "$1" in
speed)
speed_subcommand "${@:2}" ;;
accuracy)
accuracy_subcommand "${@:2}" ;;
...
This method doesn't really mix with handling multiple subcommands per run.