0

I have this script:

#!/usr/bin/env bash

first_arg=$1
second_arg=$2

while getopts ":a:b" opt; do
    case $opt in
        a)
            echo "-a found"
            some_value=$OPTARG
            ;;
        b)
            echo "-b found"
            ;;
        \?)
            echo "Unknown flag"
    esac
done

echo "$some_value"

When I call it like this: ./test.sh -a third the getopts while loop works and the output is:

-a found
third

But when I call it with 2 additional parameters like this: ./test.sh first second -a third the while loop doesn't find anything in getopts and the output is blank (i.e. because $some_value is empty). What is happening to getopts when I add more parameters to the shell script command and how do I fix it?

u84six
  • 4,604
  • 6
  • 38
  • 65
  • 1
    I believe you can't mix positional parameters and options recognized by `getopts` like this. `./test.sh -a third first second` works, but `./test.sh first second -a third` assumes there are no more options when `first`, the first positional parameter, isn't an option. – Benjamin W. Jun 26 '23 at 22:10
  • Do you mean the flag should be just treated manually like another positional argument? – u84six Jun 26 '23 at 22:13
  • I know there are many bash commands that have a format with flags after the command and after positional arguments – u84six Jun 26 '23 at 22:15
  • 2
    Yes, many frameworks to build CLI tools have argument parsing that is much more sophisticated than `getopts`. I'm not suggesting to switch to manual parsing instead, but if you use `getopts` (and assuming what I said above is actually correct), your script *must* be called with all the flags before all the positional parameters. – Benjamin W. Jun 26 '23 at 22:21
  • Is this a good duplicate? https://stackoverflow.com/q/11742996/3266847 – Benjamin W. Jun 26 '23 at 22:22
  • 4
    @u84six The "traditional" shell command syntax requires all options to come before the positional parameters. Some people (especially those working in the GNU project) didn't like this, so they wrote their commands to allow options and positional parameters to be given in any order (unless there was a `--`, in which case everything after it was a positional parameter, even if it started with `-`). Some commands (and versions of commands) use one convention, some the other. The `getopts` command was standardized before mixed-order was a thing, and only supports the traditional syntax. – Gordon Davisson Jun 26 '23 at 22:57
  • 3
    Search for "guideline 9" in https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html. Tools that allaw you to put options after positional arguments are broken and should be fixed so they no longer disobey the standard by misinterpreting positional arguments as if they were options. – Charles Duffy Jun 26 '23 at 22:59
  • The invocation `./test.sh first second -a third` is pretty non-standard and `getopts` is not designed to handle this. You would have to implement your own version this. – user1934428 Jun 27 '23 at 06:27

0 Answers0