Search code examples
bashgetoptgetopts

Parsing long command-line arguments not working with getopt


I want to parse long command-line arguments for a large script as part of my current project. I have never tried getopt before but want to try the first time to make the script look tidy.

Before trying to push getopt on that large project script, I thought of checking it first on a sample script.

In the following example script, parsing short command-line arguments work fine but not the long command-line arguments:

#!/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
        ;;
    -f|--from)
        FROM=$2;
        shift
        ;;
    -t|--to)
        TO=$2;
        shift
        ;;
    --)
        shift
        break
        ;;
    *)
        echo "Invalid options!!";
        exit 1
        ;;
    esac
    shift
done

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

Output:

# ./getopt_check.bash -d hello.com -f [email protected] -t [email protected]
Domain is hello.com
From address is [email protected]
To address is [email protected]

# ./getopt_check.bash --domain hello.com -f [email protected] -t [email protected]
Invalid options!!

# ./getopt_check.bash --domain hello.com --from [email protected] --to [email protected]
Invalid options!!

I am expecting the same output as well when parsing long command arguments:

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

When debugging:

# bash -x getopt_check.bash --domain hello.com -f [email protected] -t [email protected]
++ getopt -o d:f:t: -l domain -l from -l to -- --domain hello.com -f [email protected] -t [email protected]
+ options=' --domain -f '\''[email protected]'\'' -t '\''[email protected]'\'' -- '\''hello.com'\'''
+ '[' 0 -eq 0 ']'
+ eval set -- ' --domain -f '\''[email protected]'\'' -t '\''[email protected]'\'' -- '\''hello.com'\'''
++ set -- --domain -f [email protected] -t [email protected] -- hello.com
+ true
+ case "$1" in
+ DOMAIN=-f
+ shift
+ shift
+ true
+ case "$1" in
+ echo 'Invalid options!!'
Invalid options!!
+ exit 1

Here, the issue is passing case switch OR choice -d|--domain ?.


Solution

  • I guess its your getopt syntax. Use :

    getopt -o d:f:t: -l domain:,from:,to: -- "$@"

    Instead of :

    getopt -o d:f:t: -l domain -l from -l to -- "$@"