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).