Search code examples
bashgetoptgetopts

Unable to workaround on getopt options


I am trying to play around with getopt options. I want both short options and long options.

For my following test script, it does not produce my required output.

#!/bin/bash
 
options=$(getopt -o d:f:t: -l domain -l from -l to -- "$@")
[ $? -eq 0 ] || { 
    echo "Incorrect options provided"
    exit 1
}
eval set -- "$options"
while true; do
    case "$1" in
    -d | --domain)
        DOMAIN=$2;
        shift 2
        ;;
    -f | --from)
        FROM=$2;
        shift 2
        ;;
    -t | --to)
        TO=$2;
        shift 2
        ;;
    --)
        shift
        break
        ;;
    esac
    shift
done

echo "Domain is $DOMAIN"
echo "From address is $FROM"
echo "To address is $TO"
exit 0;

When I try to run it, nothing happens, it just hangs:

# bash getopt_check.sh -d hello.com  -f [email protected] -t [email protected]

Expecting output:

Domain is hello.com
From address is [email protected]
To address is [email protected]

Solution

  • You are shifting 3 values per option, -d hello.com are 2 positions, not three.

    -d | --domain)
        ...
        shift 2
        ...
    -f | --from)
        ...
        shift 2
        ...
    -t | --to)
        ...
        shift 2
        ...
    shift             # shift 2 + shift = shift 3!
    

    change it to:

    -d|--domain)
        shift
        ...
    -f|--from)
        shift
        ...
    -t|--to)
        shift
        ...
    shift
    

    Prefer to use lower case variables in your script - use upper case for exported variables. Check your script with http://shellcheck.net . Prefer not to use $?, instead check the command in if like if ! options=$(getopt ...); then echo "Incorrect....

    while true; do is unsafe, in case you do not handle some option it will endlessly loop. Do while (($#)); do and handle that *) echo "Internal error - I forgot to add case for my option" >&2; exit 1; ;; in the case statement.