2

I created a script with the standard getopt magic, so you can call the script with

batman-connect -c ffki

How can I add an option to call this script with only one option without dash?

batman-connect ffki

so It will interpret this only option as the second argument for -c?

According to this answer I tried:

if [ $@ = "ffki" ]; then
  set -- "-c $@"
fi

But that gives an error, I think because this line in my script will change it back:

# Execute getopt on the arguments passed to this program, identified by the special character $@
PARSED_OPTIONS=$(getopt -n "$0"  -o hsrvVi:c: --long "help,start,restart,stop,verbose,vv,version,interface:,community:"  -- "$@")

I don't like to re-arrange my whole script, so is there a simple one-liner to just set the first argument to "-c" and the second to "ffki" ?

rubo77
  • 28,966

4 Answers4

1

You can do something like

if [ $# = 1 ]; then
    # do whatever you'd do when there is only one argument
else
    # do the getopt bits
fi
# do what you'd do in either case

If -c is the only switch you want to support, then you don't need getopt and can instead do something like this:

#!/bin/bash

usage() {
    echo "Usage: $0 [ -c ] arg" >&2
    exit 1
}

if [ $# = 2 ]; then
    if [ $1 = "-c" ]; then
        shift
        c_switch_value="$1"
    else
        usage
    fi
elif [ $# = 1 ]; then
    c_switch_value="$1"
else
    usage
fi

Whether this is more readable is debatable though.

  • But then I would have to rearrange my whole script. Isnt there a way to just set the forst argument to "-c" and the second to "ffki" then? – rubo77 Sep 07 '14 at 07:29
1

I added right at the beginning of this script:

if [ $# = 1 ]; then
  # If there is only one argument, replace the current process with the new invocation of the script
  # the only option will be used as -c option
  exec "$0" -c "$@"
fi

This doesn't answer the initial question, but it a workaround, that works in my special case.

rubo77
  • 28,966
1
if [ $@ = "ffki" ]; then

The command in the if clause expands to [ followed by the list of wildcard expansions of the words that make up the positional parameters followeb by the words = ffki ]. Generally speaking, $VAR does not mean “the value of VAR” when it's outside double quotes, it means “split the value of VAR into separate words and interpret them as globs”. See Why does my shell script choke on whitespace or other special characters?

Furthermore "$@" is a special case: it expands to the list of positional parameters (without further expansion), not to a single word (despite the quotes). You can use "$*", which expands to a single word made up of the positional parameters separated by a space (more precisely, by the first character of the value of IFS). So to test whether there is a single positional parameter whose value is ffki, you can use

if [ "$*" = "ffki" ]; then

Alternatively, you can count the number of positional parameters and test their value individually. This would be necessary if you wanted to allow values containing spaces, for example.

if [ $# -eq 1 ] && [ "$1" = "ffki" ]; then

To change the positional parameters, you were close: use the set builtin, and pass the new set of positional parameters as separate arguments. If there's a risk that the first parameter begins with a -, use set -- … so that it isn't interpreted as an option.

if [ "$*" = "ffki" ]; then
  set -- -c "ffki"
fi
0

You probably want something like this:

# getopt code that sets "$c_value" goes here ...
# ... then
if [[ -z $c_value ]] && (( $# > 0 )); then
    c_value=$1
    shift
fi
glenn jackman
  • 85,964