J33nn
J33nn

Reputation: 3234

Script with non-option and option arguments

I'm trying to handle both optional and mandatory parameter to my bash script. I have following script:

while getopts "a:x:" opt; do
  case $opt in
     a) echo "option a set: $OPTARG" ;;
     x) echo "option x set: $OPTARG" ;;
     \?) echo "Invalid option: -$OPTARG" >&2; exit 1;;
esac
done
shift $((OPTIND-1))

echo "mandatory argument $1"
echo "mandatory argument2 $2"

Everything looks ok when I run my script using following command:

./script.sh -a optionA -x optionX mandatory1 mandatory2

But when I mix this params:

./script.sh mandatory1 mandatory2 -a optionA -x optionX

It doesn't... How to make it works for all combination of parameters?

Upvotes: 2

Views: 6003

Answers (2)

ams
ams

Reputation: 25559

You can iterate between both kinds of argument, I think.

I think this does what you want, and allows you to use -- to prevent the following arguments being interpreted as options.

mandatory=()
while [ $# -gt 0 ] && [ "$1" != "--" ]; do
  while getopts "a:x:" opt; do
    case $opt in
       a) echo "option a set: $OPTARG" ;;
       x) echo "option x set: $OPTARG" ;;
       \?) echo "Invalid option: -$OPTARG" >&2; exit 1;;
  esac
  done
  if [[ ${OPTIND:-0} -gt 0 ]]; then
    shift $((OPTIND-1))
  fi

  while [ $# -gt 0 ] && ! [[ "$1" =~ ^- ]]; do
    mandatory=("${mandatory[@]}" "$1")
    shift
  done
done

if [ "$1" == "--" ]; then
  shift
  mandatory=("${mandatory[@]}" "$@")
fi

echo "mandatory argument ${mandatory[0]}"
echo "mandatory argument2 ${mandatory[1]}"

Basically, the idea is to consume all the options with getopt, then consume all the non-options manually, then look for more options with getopt again.

Upvotes: 4

Slashback
Slashback

Reputation: 1

To make it work I had to unset OPTIND after the shift $((OPTIND-1)):

[...]
shift $((OPTIND-1))
unset OPTIND
[...]

Upvotes: -1

Related Questions