dockerwonderer
dockerwonderer

Reputation: 21

bash script options parser fails

I have a bashscript.sh that I $ chmod +x bashscript.sh and move it to $ mv bashscript.sh ~/.local/bin/ in order for it to be executable like a system command.

I'd like to be able to invoke it with

bashscript [<-w|-working|--working>[=|:]] <y|yes|n|no> 

And return usage/help/error (call it whatever we want) if the call isn't respected.

To do so, I wrote this parsing part:

usage(){
  echo "you're wrong."
  exit 1
}
[[ $# -lt 1 ]] && usage
options=$(getopt -o y,n,h,w: -l yes,no,help,working: -- "$@")
set -- $options
while true; do
  case "$1" in
    -h|--help|*) usage
      shift;;
    y|yes)
      #do something
      shift;;
    n|no)
      #..
      shift;;
    -w|-working|--working)
      shift;;
    --) #this is just syntax
      shift
      break;;
  esac
done

But when I test it doesn't work as intended*, would you know why/have a sample that handles my option possibilites?

*edit : I always trigger the usage display

edit 2 : removed the spaces around the "=" of options as @costaparas3 pointed out, thank you, still stuck to usage() though

Upvotes: 0

Views: 528

Answers (1)

user9706
user9706

Reputation:

Here are the issues I found:

  1. Exit if there are no arguments
  2. Set the options with options=$(... (no spaces)
  3. -h|--help|*) matches everything so you have an infinite loop. You don't need to match on * as getopt will reuturn non-zero if it finds an invalid argument, and the match on -- is what usually terminates the loop.
  4. getopt returns non-zero for invalid arguments so exit 1 then
  5. Use -n|--no to specify short and long options
  6. --working requires an argument but you only shift 1.
  7. -working is not valid (with getopt). Use either -w or --working.

Here is corrected version:

#!/bin/bash

usage() {
  echo "you're wrong."
  exit $1
}

[ $# -lt 1 ] && usage

options=$(getopt -o y,n,h,w: -l yes,no,help,working: -- "$@")
[ $? -ne 0 ] && usage 1

# default values
yes=
working=

set -- $options
while :
do
  case "$1" in
    -h|--help)
      usage
      ;;
    -y|--yes)
      yes=1
      shift
      ;;
    -n|--no)
      yes=0 # or no=1
      shift
      ;;
    -w|--working)
      working=$2
      shift 2
      ;;
    --)
      break
      ;;
  esac
done

Upvotes: 2

Related Questions