2

I'm looking for a recipe to provide a list of space-delimited IP addresses as named optional parameter to bash script. I'd like to get next functionality:

./bootstrap.sh -bx -c 192.168.1.1 192.168.1.2

Here b and x are some optional parameters and -c is supposed to get a list of IP addresses as parameter. I use getops to deal with parameters and for now I provide this parameter as comma-delimited string:

./bootstrap.sh -bx -c192.168.1.1,192.168.1.2

It works well, but looks ugly and non-intuitive for users. Any help appreciated.

Anton Kirillov
  • 1,306
  • 1
  • 9
  • 12

2 Answers2

6

Absolutely what John says. getopts triggers options several times, so if you want to go for the second syntax

./bootstrap.sh -bx -c 192.168.1.1 -c 192.168.1.2

it is easy to implement - just push your -c arguments onto an array for further processing, e.g.:

#!/bin/bash

b=0
x=0
c=()

while getopts ":bxc:" o; do
        case "${o}" in
                b) b=1 ;;
                x) x=1 ;;
                c) c+=( "${OPTARG}" ) ;;
                *) echo "usage()"; exit 1 ;;
        esac
done
shift $((OPTIND-1))

echo "b = ${b}"
echo "x = ${x}"
if (( ${#c} > 0 )); then
        for ip in "${c[@]}"; do
                ips="${ips}${ip}, "
        done
        echo "IPs = ${ips%??}"
fi
if (( $# > 0 )); then
        echo "non-option arguments: $*"
fi

Example:

$  ./test.sh foo bar quux
b = 0
x = 0
non-option arguments: foo bar quux

$  ./test.sh -bx -c 192.168.1.1 -c 192.168.1.2 foo bar quux
b = 1
x = 1
IPs = 192.168.1.1, 192.168.1.2
non-option arguments: foo bar quux
Adrian Frühwirth
  • 42,970
  • 10
  • 60
  • 71
5

There are two canonical Unix command line syntaxes you should consider choosing between:

./bootstrap.sh -bx 192.168.1.1 192.168.1.2

That is, neither -b nor -x takes an argument, and the script takes the IP addresses as positional arguments (as many as you like).

Or:

./bootstrap.sh -bx -c 192.168.1.1 -c 192.168.1.2

That is, -c takes an argument, and it can be used multiple times. This is quite conventional, and before you say it's ugly or repetitive, note that Bash or similar shells will allow you to use a shorthand which is quite similar to what you proposed initially:

./bootstrap.sh -bx -c={192.168.1.1,192.168.1.2}

The shell will expand this, making the actual invocation identical to the previous example. So if you suppose the regular -c option with argument, your shell will support the above "for free."

Please resist the temptation to invent new syntaxes like "-g foo,bar" where you parse the argument in some application-specified way. Such an approach is less amenable to integration with standard Unix tools like xargs.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 1
    +1 Maybe emphasize that non-optional input should not be specified with option syntax. In other words, if the list of IP addresses is mandatory, the first alternative is better, absolutely. – tripleee Apr 28 '13 at 12:12
  • Also worth emphasizing is that the second one requires the otherwise optional `=`; `-c {192.168.1.1,192.168.1.2}` would not repeat the `-c`. – chepner Apr 28 '13 at 13:24
  • 1
    @chepner: the `=` can be omitted so long as no space is added, i.e. `-c{192.168.1.1,192.168.1.2}`, but I prefer with the `=`. – John Zwinck Apr 28 '13 at 14:16
  • @John , thanks a lot for clear explanation of concepts! I will rework my script because I use `-c` and `-b` as mutually exclusive options whereas I could just use an empty list of addresses as `-b` without `-c`. – Anton Kirillov Apr 29 '13 at 07:03