1

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
        _NAME="$1"
        ;;
    -i | --id)
        shift
        _ID="$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.

1
  • List all the possible parameter formats. Then write code to understand that. Ex. if you always have an action parameter (create or delete in your example), store that action in a variable, call shift and the rest of the arguments are ok to be processed with your existing code. You could look into getopts as well :) Commented Jul 20, 2022 at 3:41

2 Answers 2

2

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 bash-CLI-template I have used in my projects

demo ;)

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.