Monday, June 6, 2022

[SOLVED] BASH getopt inside bash function

Issue

I would like to put my getopt call into a function so I can make my script a bit more tidy. I've read a few guides href="https://stackoverflow.com/questions/16654607/using-getopts-inside-a-bash-function">Using getopts inside a Bash function but they seem to be for getopts not getopt and cannot get my head round it.

I have the following getopt call at the start of my script

#-------------------------------------------------------------------------------
# Main
#-------------------------------------------------------------------------------
getopt_results=$( getopt -s bash -o e:h --long ENVIRONMENT:,HELP:: -- "$@" )

if test $? != 0
then
    echo "Failed to parse command line unrecognized option" >&2
    Usage
    exit 1
fi

eval set -- "$getopt_results"

while true
do
  case "$1" in
      -e | --ENVIRONMENT)
          ENVIRONMENT="$2"
          if [ ! -f "../properties/static/build_static.${ENVIRONMENT}.properties" -o ! -f "../properties/dynamic/build_dynamic.${ENVIRONMENT}.properties" ]; then
            echo "ERROR: Unable to open properties file for ${ENVIRONMENT}"
            echo "Please check they exist or supply a Correct Environment name"
            Usage
            exit 1
          else
            declare -A props
            readpropsfile "../properties/dynamic/dynamic.${ENVIRONMENT}.properties"
            readpropsfile "../properties/static/static.${ENVIRONMENT}.properties"
          fi
          shift 2
          ;;
      -h | --HELP)
          Usage
          exit 1
     ;;
      --)
         shift
         break
         ;;
      *)
         echo "$0: unparseable option $1"
         Usage
         exit 1
         ;;
  esac
done

when I put the whole lot in function , say called parse_command_line () and call it with parse_command_line "$@" my script dies because it cannot work out the parameters it was called with. I have tried making OPTIND local as per some of the guides. Any advice? Thanks.


Solution

getopt shouldn't be used, but the bash-aware GNU version works fine inside a function, as demonstrated below:

#!/usr/bin/env bash

main() {
    local getopt_results
    getopt_results=$(getopt -s bash -o e:h --long ENVIRONMENT:,HELP:: "$@")

    eval "set -- $getopt_results" # this is less misleading than the original form

    echo "Positional arguments remaining:"
    if (( $# )); then
      printf ' - %q\n' "$@"
    else
      echo "   (none)"
    fi
}

main "$@"

...when saved as getopt-test and run as:

./getopt-test -e foo=bar "first argument" "second argument"

...properly emits:

Positional arguments remaining:
 - -e
 - foo=bar
 - --
 - hello
 - cruel
 - world


Answered By - Charles Duffy
Answer Checked By - Mildred Charles (WPSolving Admin)