Search code examples
bashgetopt

Is it possible to call one option and it's argument for more times in one command?


It is my bash case test-getopt.sh to understand getopt in bash.

OPTS=$(getopt -o d:eh   -- "$@")
eval set -- "$OPTS"
while true; do
    case "$1" in
        -d ) 
            if [[ $2  ==  "a"  ]];then
                echo  "i am -d's arg :a"
            elif [[ $2  ==  "b"  ]];then
                echo  "i am -d's arg :b"
            fi
            shift;;
        -e )   
            echo "i  am e"
            shift;;
        -h)
            echo "help you"
            shift;;
        -- ) 
            shift;; 
        *)
            break;;
    esac
done

To call for option and it's argument,one option and it's argument for one time.

bash test-get.sh  -d  a
i am -d's arg :a

Other argument.

bash test-get.sh  -d  b
i am -d's arg :b

I want to call option and it's all argument in one command

bash test-get.sh  -d  a -d b
i am -d's arg :a

Is there a way to get the following expect output?

bash test-get.sh  -d  a -d b
i am -d's arg :a
i am -d's arg :b

Solution

  • The basic problem is that when you process an option that takes an argument, you need to shift twice to remove both the option and its argument from the arg list. Like this:

    OPTS=$(getopt -o d:eh   -- "$@")
    eval set -- "$OPTS"
    while true; do
        case "$1" in
            -d ) 
                if [[ $2  ==  "a"  ]];then
                    echo  "i am -d's arg :a"
                elif [[ $2  ==  "b"  ]];then
                    echo  "i am -d's arg :b"
                fi
                shift 2;;   # <-- The "2" here is the only change
            -e )   
                echo "i  am e"
                shift;;
            -h)
                echo "help you"
                shift;;
            -- ) 
                shift;; 
            *)
                break;;
        esac
    done
    

    Without the double shift, what happens is that on the first time through the loop the arg list is "-d" "a" "-d" "b" "--". You detect the "-d" and "a", print appropriately, and then shift, which leaves the arg list as "a" "-d" "b" "--". On the second time through the loop, it fails to match "a" as an option, executes the *) case, and breaks out of the processing loop.