Bash Shell Script - Check for a flag and grab its value
You should read this getopts tutorial.
Example with -a
switch that requires an argument :
#!/bin/bashwhile getopts ":a:" opt; do case $opt in a) echo "-a was triggered, Parameter: $OPTARG" >&2 ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esacdone
Like greybot said(getopt
!= getopts
) :
The external command getopt(1) is never safe to use, unless you know it is GNU getopt, you call it in a GNU-specific way, and you ensure that GETOPT_COMPATIBLE is not in the environment. Use getopts (shell builtin) instead, or simply loop over the positional parameters.
Use $#
to grab the number of arguments, if it is unequal to 2 there are not enough arguments provided:
if [ $# -ne 2 ]; then usage;fi
Next, check if $1
equals -t
, otherwise an unknown flag was used:
if [ "$1" != "-t" ]; then usage;fi
Finally store $2
in FLAG
:
FLAG=$2
Note: usage()
is some function showing the syntax. For example:
function usage { cat << EOFUsage: script.sh -t <application>Performs some activityEOF exit 1}
Here is a generalized simple command argument interface you can paste to the top of all your scripts.
#!/bin/bashdeclare -A flagsdeclare -A booleansargs=()while [ "$1" ];do arg=$1 if [ "${1:0:1}" == "-" ] then shift rev=$(echo "$arg" | rev) if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ] then bool=$(echo ${arg:1} | sed s/://g) booleans[$bool]=true echo \"$bool\" is boolean else value=$1 flags[${arg:1}]=$value shift echo \"$arg\" is flag with value \"$value\" fi else args+=("$arg") shift echo \"$arg\" is an arg fidoneecho -e "\n"echo booleans: ${booleans[@]}echo flags: ${flags[@]}echo args: ${args[@]}echo -e "\nBoolean types:\n\tPrecedes Flag(pf): ${booleans[pf]}\n\tFinal Arg(f): ${booleans[f]}\n\tColon Terminated(Ct): ${booleans[Ct]}\n\tNot Mentioned(nm): ${boolean[nm]}"echo -e "\nFlag: myFlag => ${flags["myFlag"]}"echo -e "\nArgs: one: ${args[0]}, two: ${args[1]}, three: ${args[2]}"
By running the command:
bashScript.sh firstArg -pf -myFlag "my flag value" secondArg -Ct: thirdArg -f
The output will be this:
"firstArg" is an arg"pf" is boolean"-myFlag" is flag with value "my flag value""secondArg" is an arg"Ct" is boolean"thirdArg" is an arg"f" is booleanbooleans: true true trueflags: my flag valueargs: firstArg secondArg thirdArgBoolean types: Precedes Flag(pf): true Final Arg(f): true Colon Terminated(Ct): true Not Mentioned(nm): Flag: myFlag => my flag valueArgs: one => firstArg, two => secondArg, three => thirdArg
Basically, the arguments are divided up into flags booleans and generic arguments.By doing it this way a user can put the flags and booleans anywhere as long as he/she keeps the generic arguments (if there are any) in the specified order.
Allowing me and now you to never deal with bash argument parsing again!
You can view an updated script here
This has been enormously useful over the last year. It can now simulate scope by prefixing the variables with a scope parameter.
Just call the script like
replace() ( source $FUTIL_REL_DIR/commandParser.sh -scope ${FUNCNAME[0]} "$@" echo ${replaceFlags[f]} echo ${replaceBooleans[b]})
Doesn't look like I implemented argument scope, not sure why I guess I haven't needed it yet.