Search code examples
bashmacosgetopts

Mac OS: Bash GetOpts Sometimes Ignored


I wrote a small bash script in my bash_profile. I want to use getopts to parse options.

deployMenu() {
  noInstallDependencies='false'
  build='true'
  echo "Args: $@"

  while getopts 'db' flag; do
    echo "flag ${flag}"
    case "${flag}" in
      d) noInstallDependencies='true' ;;
      b) build='false' ;;
      #*) echo "Unexpected option ${flag}" ;;
      #\?) echo "Unexpected option ${flag}" ;;
    esac
  done

  echo "noInstallDependencies $noInstallDependencies"
  echo "build $build"

If I run the command multiple times, the argument is ignored. I have to run diff. flags in order to get it recognized.

User:project User$ deployMenu -b
Args: -b
noInstallDependencies false
build true

User:project User$ deployMenu -b
Args: -b
noInstallDependencies false
build true

User:project User$ deployMenu --b -b
Args: --b -b
flag b
noInstallDependencies false
build false

User:project User$ deployMenu --b -b
Args: --b -b
noInstallDependencies false
build true

As you can see the flag is only recognized after altering the params from -b to --<something> -b. I first thought the first param is ignored but running twice --b -b also fails. Is there any cache or anything to reset first? To get it working by first using -b and then switching to --b -b is reproducible.


Solution

  • Since you are calling a shell function repeatedly in the same shell instance, the value of $OPTIND isn't being reset between calls to deployMenu. This affects which option getopts sees as "next" each time it is called. Try your same experiment with deployMenu ...; echo $OPTIND. The solution is probably just to explicitly set OPTIND=1 if you plan on calling deployMenu multiple times.

    deployMenu() {
      noInstallDependencies='false'
      build='true'
      echo "Args: $@"
      OPTIND=1
    
      while getopts 'db' flag; do
       ...
    }