How to specify the same option multiple times using Bash

Write a simple Bash shell script that will allow to specify the same option multiple times or provide multiple arguments to single option.

You can use the code from a single example or mix every described solution. It is up to you.

First case

Repeat specific option to provide multiple arguments.

$ bash case-a.sh -p "first argument" -p "second one" -p "third one"
Provided arguments:
  "first argument"
  "second one"
  "third one"

I will use an array to store multiple arguments for a specific option.

#!/bin/bash
# How to specify the same option multiple times using Bash - case A
# https://blog.sleeplessbeastie.eu/
# milosz at sleeplessbeastie.eu

# usage info
usage(){
  echo "Usage:"
  echo "  $0 -p argument"
  echo ""
  echo "Options:"
  echo "  -p argument : set a single option with argument, repeat it multiple times"
  echo ""
  exit
}

# parse options and arguments
while getopts "p:" option; do
  case $option in
    "p")
      arguments+=("$OPTARG")
      ;;
    *)
      usage
      ;;
  esac
done

# no options were provided or there was a mistake
if [ "$OPTIND" -eq "1" ] || [ "$OPTIND" -le "$#" ]; then
  usage
fi

# result
echo "Provided arguments:"
for argument in "${arguments[@]}"; do
  echo "  \"${argument}\""
done

Second case

Pass multiple arguments to a single or multiple options.

$ bash case-b.sh -p "first argument" "second one" -p "third one"
Provided arguments:
  "first argument"
  "second one"
  "third one"

I will use an array to store multiple options for a specific option, but this time you can provide multiple arguments to single option at once.

#!/bin/bash
# How to specify the same option multiple times using Bash - case B
# https://blog.sleeplessbeastie.eu/
# milosz at sleeplessbeastie.eu

# usage info
usage(){
  echo "Usage:"
  echo "  $0 -p argument-a argument-b argument-x"
  echo ""
  echo "Options:"
  echo "  -p argument : set multiple arguments"
  echo ""
  exit
}

# parse options and arguments
while getopts "p:" option; do
  case $option in
    "p")
      arguments+=("$OPTARG")
      while [ "$OPTIND" -le "$#" ] && [ "${!OPTIND:0:1}" != "-" ]; do 
        arguments+=("${!OPTIND}")
        OPTIND="$(expr $OPTIND \+ 1)"
      done
      ;;
    *)
      usage
      ;;
  esac
done

# no options were provided or there was a mistake
if [ "$OPTIND" -eq "1" ] || [ "$OPTIND" -le "$#" ]; then
  usage
fi

echo "Provided arguments:"
for argument in "${arguments[@]}"; do
  echo "  \"${argument}\""
done

Third case

This time I will use different approach and take advantage of the double-dash to provide multiple arguments as double-dash (--) is used as delimiter indicating the end of options, but you can use it provide multiple arguments like filenames.

$ bash case-c.sh -- "first argument" "second one" "third one"
Provided additional arguments:
  "first argument"
  "second one"
  "third one"

I will use an array to store multiple arguments after double-dash and ignore regular option for now.

#!/bin/bash
# How to specify the same option multiple times using Bash - case C
# https://blog.sleeplessbeastie.eu/
# milosz at sleeplessbeastie.eu

# usage info
usage(){
  echo "Usage:"
  echo "  $0 -p argument -- additional-arguments"
  echo ""
  echo "Parameters:"
  echo "  -p argument : set single parameter"
  echo ""
  exit
}

# parse options and arguments
while getopts "p:" option; do
  case $option in
    "p")
      single_argument="$OPTARG"
      ;;
    *)
      usage
      ;;
  esac`
done

# shift options/arguments list
shift $(($OPTIND - 1))

# parse additional arguments
while [ "$#" -gt "0" ]; do
  arguments+=("$1")
  shift
done

# no options were provided or there was a mistake
if [ "$OPTIND" -eq "1" ] || [ "$OPTIND" -le "$#" ]; then
  usage
fi

echo "Provided additional arguments:"
for argument in "${arguments[@]}"; do
  echo "  \"${argument}\""
done