Home > Back-end >  Bash subcommands with arguments
Bash subcommands with arguments

Time:07-20

I have a script in bash as such:

#!/usr/bin/env bash
set -e

if [[ "$#" == 0 ]]; then
    printhelp
    exit 1
fi

# process options
while [[ "$1" != "" ]]; do
    case "$1" in
    -n | --name)
        shift
        IAM_APIKEY="$1"
        ;;
    -i | --id)
        shift
        IAM_APIKEY_PROD="$1"
        ;;
    -h | --help)
        printhelp
        exit 1
        ;;
    *)
        printhelp
        exit 1
        ;;
    esac
    shift
done

This works fine, but I want to add some "actions" that will take the above params. Eg. usage will be:

./run.sh create --name foo --id 1234
./run.sh delete --id 1234

I am not able to figure out the right syntax, and I am unable to phrase this requirement into appropriate words to be able to search.

CodePudding user response:

Sounds like you want something like:

create() {
     # actiony stuff here
}
ACTION=$1 ; shift
# put all your argument parsing here
$ACTION   # call 

However, since different actions probably have different arguments, I'd probably do it differently...

create() {
    # argument parsing for create
    # then do your create stuff
}
ACTION=$1 ; shift
$ACTION "$@"

This will pass all your arguments to your subfunction, which can then parse its own arguments.

CodePudding user response:

For sub-command you can handle it this way:

function main(){
    if (( ${#} == 0 )); then
        main_help 0;
    fi

    case ${1} in
        help | version | encrypt | decrypt )
            $1 "${@:2}";
        ;;
        * )
            echo "unknown command: $1";
            main_help 1;
            exit 1;
        ;;
    esac
}

main "$@";

Then wrap each sub-command is a function. And inside each function you will have isolated options and parsing it separately.

For example:

function decrypt(){
    if [[ ${#} == 0 ]]; then
        decrypt_help;
    fi

    local __filename='';
    local __salt='';
    local __anchor=false;
    local error_message='';

    while [ ${#} -gt 0 ]; do
        error_message="Error: a value is needed for '$1'";
        case $1 in
            -f | --file )
                __filename=${2:?$error_message}
                shift 2;
            ;;
            -s | --salt )
                __salt=${2:?$error_message}
                shift 2;
            ;;
            -a | --anchor )
                __anchor=${2:?$error_message}
                shift 2;
            ;;
            * )
                echo "unknown option $1";
                break;
            ;;
        esac
    done

    echo filename: ${__filename:-empty};
    echo salt: ${__salt:-empty};
    echo anchor: $__anchor;

    exit 0;
}

Here is a full version enter image description here

  • Related