Explain the shell command: shift $(($optind – 1))

I am not a Linux guy but stuck in some Script which I have to read for my Project.
So can anyone can help me what this command is doing?

shift $(($optind - 1))
Asked By: Gaurav Pant

||

$((...)) just calculates stuff. In your case it takes the value of $optint and substracts 1.

shift removes positional parameters. In your case it removes optint-1 parameters.

For more information have a look at help getopts, help shift, look at man bash for “Arithmetic Expansion”, and especially google for getopts.

Answered By: michas

shift $((OPTIND-1)) (note OPTIND is upper case) is normally found immediately after a getopts while loop. $OPTIND is the number of options found by getopts.

As pauljohn32 mentions in the comments, strictly speaking, OPTIND gives the position of the next command line argument.

From the GNU Bash Reference Manual:

getopts optstring name [args]

getopts is used by shell scripts to parse positional parameters.
optstring contains the option characters to be recognized; if a
character is followed by a colon, the option is expected to have an
argument, which should be separated from it by whitespace. The colon
(‘:’) and question mark (‘?’) may not be used as option characters.
Each time it is invoked, getopts places the next option in the shell
variable name, initializing name if it does not exist, and the index
of the next argument to be processed into the variable OPTIND.
OPTIND is initialized to 1 each time the shell or a shell script is
invoked. When an option requires an argument, getopts places that
argument into the variable OPTARG. The shell does not reset OPTIND
automatically; it must be manually reset between multiple calls to
getopts within the same shell invocation if a new set of parameters
is to be used.

When the end of options is encountered, getopts exits with a return
value greater than zero. OPTIND is set to the index of the first
non-option argument, and name is set to ‘?’.

getopts normally parses the positional parameters, but if more
arguments are given in args, getopts parses those instead.

shift n
removes n strings from the positional parameters list. Thus shift $((OPTIND-1)) removes all the options that have been parsed by getopts from the parameters list, and so after that point, $1 will refer to the first non-option argument passed to the script.

Update

As mikeserv mentions in the comment, shift $((OPTIND-1)) can be unsafe. To prevent unwanted word-splitting etc, all parameter expansions should be double-quoted. So the safe form for the command is

shift "$((OPTIND-1))"

Answered By: PM 2Ring

The other answers are correct. To summarize:

  1. The expression is normally found immediately after a getopts while loop. $OPTIND is the number of options found by getopts.

  2. OPTIND gives the position of the next command line argument.

However, this short expression contains 2 syntax errors! They have propagated throughout the interwebs. The correct syntax is:

shift "$((OPTIND-1))"
  1. Within parentheses, the variable reference does not require a leading dollar sign.
  2. Expressions yielding values should be double-quoted, to guard against results containing embedded spaces
Answered By: Mike Slinn
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.