bash script options arguments param getopts - ghdrako/doc_snipets GitHub Wiki
gengetops
Gengetopt is a tool to generate C code to parse the command line arguments argc and argv that are part of every C or C++ program. The generated code uses the C library function getopt_long to perform the actual command line parsing.
getopts
getopts is a command that comes built-in with Bash. getopts is a built-in Bash command for parsing short options (single-letter options) in a script.
while getopts ":a:b:" option; do
case "$option" in
a)
echo "You chose option 'a' with value: $OPTARG"
;;
b)
echo "You chose option 'b' with value: $OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
exit 1
;;
:)
echo "Option -$OPTARG requires an argument."
exit 1
;;
esac
done
- Execution:
./getopts_example.sh -a apple -b banana
- Output:
You chose option 'a' with value: apple
You chose option 'b' with value: banana
#!/bin/bash
while getopts a:b:c: OPTION; do
case $OPTION
a) echo "You select option a with $OPTARG";;
b) echo "Option b with $OPTARG";;
c) echo "c with $OPTARG";;
*) echo "Not valid option";;
esac
done
!/bin/bash
OPTSTRING=":x:y:"
while getopts ${OPTSTRING} opt; do
case ${opt} in
x)
echo "Option -x was triggered, Argument: ${OPTARG}"
;;
y)
echo "Option -y was triggered, Argument: ${OPTARG}"
;;
:)
echo "Option -${OPTARG} requires an argument."
exit 1
;;
?)
echo "Invalid option: -${OPTARG}."
exit 1
;;
esac
done
Parsing Command Line Options Using Positional Parameters
param="${1:-default_value}"
Positional Parameters - simple numerically indexed array of strings (in fact, in the POSIX shell, they are the only array the shell has). The first positional parameter is referred to with $1
; the second, with $2
; and so on. After the 9th one, you must use curly braces to refer to them: ${10}, ${11}
, etc.
"$@"
substitution - refer to the entire set of positional parameters. The double quotes here are extremely important!! By using the quotes, you tell Bash that you want to preserve each parameter as a separate word.
shift
- deal with the positional parameters is to eliminate each one as it is used. When you issue the shift command, the first positional parameter ($1)
goes away. The second one becomes $1
, the third one becomes $2
, and so on down the line. So, if you wish, you can write a loop that keeps using $1
over and over.
#!/bin/bash
if [ "$#" -lt 3 ]; then
echo "Usage: ./run_oncloud.sh project-name bucket-name classname [options] "
echo "Example: ./run_oncloud.sh cloud-training-demos cloud-training-demos CurrentConditions --bigtable"
exit
fi
PROJECT=$1
shift
BUCKET=$1
shift
MAIN=com.google.cloud.training.dataanalyst.sandiego.$1
shift
echo "Launching $MAIN project=$PROJECT bucket=$BUCKET $*"
export PATH=/usr/lib/jvm/java-8-openjdk-amd64/bin/:$PATH
mvn compile -e exec:java \
-Dexec.mainClass=$MAIN \
-Dexec.args="--project=$PROJECT \
--stagingLocation=gs://$BUCKET/staging/ $* \
--tempLocation=gs://$BUCKET/staging/ \
--runner=DataflowRunner"
tar -x -f archive.tar -v -- file1 file2 file3
This command has some arguments (file1, file2, file3), and some options (-x -f archive.tar -v), as well as the traditional end of options indicator --
.
The options appear before the non-option arguments. They do not appear afterward. They do not appear at just any old random place in the command.
Some options (-x, -v) are standalones. They are either present, or not. Some options (-f) take an argument of their own
There are two basic approaches to writing an option processing loop: either write the loop yourself from scratch (we'll call this a "manual loop"), or use the shell's getopts command to assist with option splitting.
Manual loop
For more complex scripts or long options, case statements can be used to parse command-line options.
#!/bin/sh
# POSIX
die() {
printf '%s\n' "$1" >&2
exit 1
}
# Initialize all the option variables.
# This ensures we are not contaminated by variables from the environment.
file=
verbose=0
while :; do
case $1 in
-h|-\?|--help)
show_help # Display a usage synopsis.
exit
;;
-f|--file) # Takes an option argument; ensure it has been specified.
if [ "$2" ]; then
file=$2
shift
else
die 'ERROR: "--file" requires a non-empty option argument.'
fi
;;
--file=?*)
file=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
--file=) # Handle the case of an empty --file=
die 'ERROR: "--file" requires a non-empty option argument.'
;;
-v|--verbose)
verbose=$((verbose + 1)) # Each -v adds 1 to verbosity.
;;
--) # End of all options.
shift
break
;;
-?*)
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
;;
*) # Default case: No more options, so break out of the loop.
break
esac
shift
done
# if --file was provided, open it for writing, else duplicate stdout
if [ "$file" ]; then
exec 3> "$file"
else
exec 3>&1
fi
# Rest of the program here.
# If there are input files (for example) that follow the options, they
# will remain in the "$@" positional parameters.
This parser does not handle single-letter options concatenated together (like -xvf being understood as -x -v -f).