0

This is my entire script in its simplest form.

#!/bin/bash
src=""
targ=${PWD}

while getopts "s:t:" opt; do
  case $opt in
    s)
      src=$OPTARG
      ;;
    t)
      targ=$OPTARG
      ;;
  esac
  shift $((OPTIND-1))
done

echo "Source: $src"
echo "Target: $targ"

I run this script as getopts_test -s a -t b

However, it always prints the pwd in front of the Target: and never b

What am I missing here?

Cyrus
  • 84,225
  • 14
  • 89
  • 153
kshenoy
  • 1,726
  • 17
  • 31
  • probably this might help http://stackoverflow.com/questions/16483119/example-of-how-to-use-getopts-in-bash – Naruto Dec 05 '15 at 04:31
  • 4
    try taking the `shift` out of the while loop: move it to after `done` – glenn jackman Dec 05 '15 at 04:36
  • 1
    When you do the shift inside the loop, you remove the `-s` and `a` arguments from the argument list, but `getopts` still thinks it processed arguments 1 and 2 (which now contain `-t` and `b`), so it looks beyond them and says "nothing else to do". – Jonathan Leffler Dec 05 '15 at 04:44
  • Got it. Thanks for the detailed explanation – kshenoy Dec 07 '15 at 00:45

2 Answers2

5

The reason for why b is never printed is that the shift within the loop moves the processed options away after the first iteration, i.e. after a has been printed. Use of shift $((OPTIND-1)) is intended to access the possible given variadic parameters. Naturally, once you remove shift, targ gets reassigned to b, and ${PWD} is no longer included in it since you don't have concatenation of the strings (targ and the option of -t) anywhere.

Ville
  • 4,088
  • 2
  • 37
  • 38
3

An alternative to what @glenn-jackman suggested in his comment would be this :

#!/bin/bash
src=""
targ=${PWD}

while getopts "s:t:" opt; do
  case $opt in
    s)
      src=$OPTARG
      echo "Source: $src"
      ;;
    t)
      targ=$OPTARG
      echo "Target: $targ"
      ;;
  esac

done

shift $((OPTIND-1)) # Turning to non-option arguments say a file name and so on.

Here you go with the natural flow of arguments without shifting.

sjsam
  • 21,411
  • 5
  • 55
  • 102
  • The shift is needed after the loop so that you can remove the option arguments (and `--`) and leave `"$@"` with just the non-option arguments. – Jonathan Leffler Dec 05 '15 at 06:01
  • @JonathanLeffler : Thankyou for reminding about the non-option args. Edited the answer. :) – sjsam Dec 05 '15 at 06:25