I am currently writing a BASH script in which I would like to use both positional and optional arguments. The positional arguments must occur at the location specified (ex: $1, $2) while the optional arguments can occur at any position denoted by their command line flag. Here is my script:
#!/usr/bin/env bash
usage() {
cat << EOF
Usage: progam ACTION NAME -k KEY_NAME
ACTION ...... The program action to initiate
NAME ........ The name of the object to create
KEY_NAME .... The key name to use
EOF
}
ACTION=$1
NAME=$2
KEY_NAME=""
while getopts "k:" opt; do
case $opt in
k) KEY_NAME=$OPTARG; ;;
[?]) usage && exit 1;
esac
done
if [[ ! $ACTION ]]; then
echo "Please select an action."
exit 1
fi
if [[ ! $NAME ]]; then
echo "Please include a name for the object."
exit 1
fi
if [[ "$KEY_NAME" != "" ]]; then
python3 -m program $ACTION -k $KEY_NAME -n $NAME
else
echo "Please include a key name."
exit 1
fi
exit 0
to run the program I would expect to be able to do the following:
fun_bash [action] [name] -k [key_name]
Where the things in brackets would be replaced by actual strings. When I execute, I always hit the condition that the key name does not exist:
Please include a key name.
How can I include mandatory positional arguments and optional command line flags within the same script?
You may be be able to use a work-around in your current script as:
#!/usr/bin/env bash
usage() {
cat << EOF
Usage: progam ACTION NAME -k KEY_NAME
ACTION ...... The program action to initiate
NAME ........ The name of the object to create
KEY_NAME .... The key name to use
EOF
}
action="$1"
name="$2"
shift 2
key_name=""
while getopts "k:" opt || :; do
case $opt in
k) key_name=$OPTARG; break ;;
[?]) shift;;
esac
done
if [[ -z $action ]]; then
echo "Please select an action."
exit 1
fi
if [[ -z $name ]]; then
echo "Please include a name for the object."
exit 1
fi
if [[ -n $key_name ]]; then
python3 -m program $action -k $key_name -n $name
else
echo "Please include a key name."
exit 1
fi
Key difference is use of shift 2 before while loop that shifts argument by 2 positions since your first 2 arguments are fixed.
Also note use of [?]) shift;; inside getopts loop which shifts an argument every time it doesn't meet known options i.e. -k.
Also note that you should avoid using all uppercase variable names in your script to avoid overriding a builtin shell variable.
With these changes all the following command lines are accepted:
fun_bash arg1 arg2 -k mykey
fun_bash arg1 arg2 arg3 arg4 -k mykey
fun_bash arg1 arg2 arg3 arg4 arg5 -k mykey
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With