1

So, I've learned how to pass in arguments in my bash script. The next step for me is to pass in a flag with the argument. For example,-id 12345, -d YES or -d NO, -h localhost.

So, I'm looking to execute like so: ./Build.sh -id 12345 -d YES -h localhost

Currently, I'm doing it this way: ./Build.sh 12345 YES localhost

Is getopt, getopts what I'm after? If so, can you show me how I use this with my script?

My working script thus far:

if [[ $# != 3 ]]; then
   echo "Usage: ./Build.sh <CUSTID> <YES|NO> <HOST>" 2>&1
   exit 1
fi

# Checks for YES or NO option for Create.sql script
case $2 in
    YES|NO)
       filename="Build_$2.sql"
       ;;
    *)echo "Must enter YES or NO"
      exit 1
      ;;
esac
noober
  • 1,427
  • 3
  • 23
  • 36
  • 1
    `-id` is not a valid switch in `getopts`, it is equivalent to `-i -d`. Long options require a double-dash: so, `--id` would be fine. – Amadan May 22 '15 at 04:16
  • ok, i'm fine with that. let's just keep it simple with `-i` – noober May 22 '15 at 04:17
  • 2
    http://mywiki.wooledge.org/BashFAQ/035 and (linked from that page) http://mywiki.wooledge.org/ComplexOptionParsing) – Etan Reisner May 22 '15 at 04:20
  • You definitely need to look at [Using `getopts` in bash shell script to get long and short command line options](http://stackoverflow.com/questions/402377). I'm not sure whether there's a reason not to close this as a duplicate of that. – Jonathan Leffler May 22 '15 at 04:39

3 Answers3

3
#!/bin/bash

script="$0"
usage() {
  echo "Usage: $script <CUSTID> <YES|NO> <HOST>" 1>&2;
  exit 1;
}

while getopts ":i:d:h:" o; do
  case "${o}" in
    i)
      i=${OPTARG}
      ;;
    d)
      d=${OPTARG}
      if [[ "$d" != YES && "$d" != NO ]]; then
        usage
      fi
      ;;
    h)
      h=${OPTARG}
      ;;
    *)
      usage
      ;;
  esac
done
shift $((OPTIND-1))

if [[ -z "$i" || -z "$d" || -z "$h" ]]; then
  usage
fi

echo i: $i, d: $d, h: $h, rest: $@

However, -h is by convention reserved for "help"; you may or may not wish to change it.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Thanks. This is nice. Can you elaborate on `script="$0"` and the `shift $((OPTIND-1))` and what that does? – noober May 22 '15 at 04:43
  • 1
    `$0` is the "0-th parameter" - the name by which you invoked the script. `./../foo.sh bar 2` has `./../foo.sh` as `$0`, just like it has `bar` for `$1`; I use it to print usage without hardcoding the name. `$OPTIND` is the index of the option that is currently processed; it will be the index of the first non-option argument when `getopts` loop is done. The `shift` then removes all the option arguments from the argument array. – Amadan May 22 '15 at 04:46
  • One other thing. How would I enforce my `YES|NO` option? I would want the user to enter one or the other. Thanks. – noober May 22 '15 at 04:54
  • Also, how do I enforce usage for incomplete entry? For example, I tested by running just as `./Build.sh` with no parameters, but the usage didn't show. – noober May 22 '15 at 05:40
  • Yes, enforce that all (3) are entered. – noober May 22 '15 at 05:51
0

If you use long options, i.e., an option with more than 1 character, you must put double-dash before it if you usegetopts. However, getopt support long option with single dash with -a. You can try getopt -h to see the detail, like

 -a, --alternative            Allow long options starting with single -

Besides, getopt is a standalone program while getopts is a bash built-in command. I use the former usually.

seven7e
  • 798
  • 1
  • 8
  • 19
0

Command line operated programs are traditional. They take their arguments from the command line that the program needs to know. Besides arguments, these programs often take command line options as well.

Complicated programs might need not only 'Arguments' but 'Options' too.

For example : A program will be verbose or not. ksh MyProgram -v true Or ksh MyProgram -v false

Command line options come in several flavours. Historically, they are preceded by a single dash - , and consist of a single letter.

`-l -a -c`

Usually, these single-character options can be bundled:

`-lac`

Options can have values, the value is placed after the option character ( as shown in the first example or verbose true or false )

`-s 24` OR  `-s24`

Due to the very cryptic nature of these options, another style was developed that used long names. So instead of a cryptic -l one could use the more descriptive --long . To distinguish between a bundle of single-character options and a long one, two dashes are used to precede the option name. Early implementations of long options used a plus + instead. Also, option values could be specified either like

--size=24 or --size 24

The + form is now obsolete and strongly deprecated.

A very detailed explanation of long getOpts is available at http://perldoc.perl.org/Getopt/Long.html

Note : A note of caution. getopts is note very smart. Users must be aware of it's pitfalls. Though it is meant to make argument processing easier, but it could be error-prone if not used cautiously.

Piyush Baijal
  • 281
  • 4
  • 13