3

I have a shell script that takes parameters, below is the code..

Right now it will only accept parameters if passed if called like this: script.sh --mode=load (or -m=load)

Is there a way to modify this so that it can be called with or without the "=" sign, so that I can call: script.sh --mode load (or -m load)

Ideally needs to work in pure bash as I don't have access to install additional tools, etc.

for i in "$@"
do
case $i in
 -m=*|--mode=*)
 MODE="${i#*=}"
  if [[ $MODE =~ ^(dump|load)$ ]]; then
   echo "" > /dev/null
  else
   bark "Invalid --mode set, set this to dump or load.";
   exit 1
  fi
 ;;
 -p=*|--db-path=*)
 DBPATH="${i#*=}"
 ;;
 -d=*|--dump-dir=*)
 DUMPDIR="${i#*=}"
 ;;
 -l=*|--list-file=*)
 TABLES="${i#*=}"
  # check if file exists on disk
  if [ -e $TABLES ]
  then
   echo "" >> /dev/null
  else
   bark "Table file not found!";
   exit 1
  fi
 ;;
 -t=*|--tenant-name=*)
 TENANT="${i#*=}"
  # check if tenant is correct
  if [[ $TENANT =~ ^($TENANT_LIST)$ ]]; then
   echo "" >> /dev/null
  else
   bark "Tenant name does not match, aborting.";
   exit 1
  fi
 ;;
 -s|--shared)
 SHARED=YES
 ;;
 *) usage # unknown option
 ;;
esac
done

My bash version:

bash --version

GNU bash, version 4.3.22(1)-release (powerpc-ibm-aix5.1.0.0)

2
  • Don't reinvent the wheel. If you want to support long options, install the GNU getopt command. Commented Jun 8, 2018 at 15:45
  • I do not know which version of AIX you run, but on my V6 here, getopt is installed by default. Commented Jun 8, 2018 at 15:50

2 Answers 2

1

Loop on $@. When $1 is "-m", do a shift. So in the next loop $1 will now be the argument to the -m option.

script.sh --mode load

# FIRST LOOP
$@ is "--mode load"
$1 is "--mode"   
shift

# SECOND LOOP
$@ is "load"
$1 is "load"

This is also useful if you can specify many arguments instead of just one like you have right now. Error checking should be done to validate your argument values, and if a user did script.sh --mode with no other argument.

Sign up to request clarification or add additional context in comments.

Comments

0

Don't reinvent the wheel.

If you're OK with just 1 character options, use the bash builtin getopts

#!/bin/bash

while getopts :m:p:d:l:t:s opt; do
    case $opt in
        m) mode=$OPTARG ;;
        p) dbpath=$OPTARG ;;
        d) dumpdir=$OPTARG ;;
        l) tables=$OPTARG
           # test file existence
           ;;
        t) tenant=$OPTARG
           # test tenant
           ;;
        s) shared=YES ;;
        :) echo "Missing argument for option -$OPTARG" >&2 
           exit 2
           ;;
        *) echo "Invalid option -$OPTARG" >&2
           exit 2
           ;;
    esac
done
shift $((OPTIND - 1))

cat << SHOW_VARS
I have:
mode=$mode
dbpath=$dbpath
dumpdir=$dumpdir
tables=$tables
tenant=$tenant
shared=$shared
rest of args=$*
SHOW_VARS

Otherwise, you may be able to use the external getopt program to help parse your args. I don't have an AIX box to test on, so YMMV

tempargs=$(
    getopt \
        -o m:d:l:t:s \
        --long mode:,db-path:,dump-dir:,list-file:,tenant-name:,shared \
        -- "$@"
)
if [[ $? -ne 0 ]]; then echo "Error..." >&2; exit 2; fi
eval set -- "$tempargs"

while true; do
    case $1 in
        -m|--mode) mode=$2; shift 2;;
        -p|--db-path) dbpath=$2; shift 2;;
        -d|--dump-dir) dumpdir=$2; shift 2;;
        -l|--list-file) tables=$2
           # test file existence
           shift 2
           ;;
        -t|--tenant-name) tenant=$2
           # test tenant
           shift 2
           ;;
        -s|--shared) shared=YES; shift;;
        --) shift; break ;;
        *) echo "Error..." >&2; exit 2 ;;
    esac
done

3 Comments

There is a /usr/bin/getopt program; getoption --version = version --.
Trying your 2nd option does not seem to work, is there a way to use your first example but with long character options?
I've only seen truly horrific hacks to force getopts to play with long options.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.