Home > database >  Bash menu script with possibility to run with arguments
Bash menu script with possibility to run with arguments

Time:06-21

I have a bash script:

PS3='Please enter your choice: '
options=("1" "2" "3" "4" "Quit")
select opt in "${options[@]}"
do
    case $opt in
        "1")
            echo "Set configuration"
            break
            ;;
        "2")
            echo "Setting configuration and execution Install"
            break
            ;;
        "3")
            echo "Setting configuration and execution Unlink"
            break
            ;;
        "4")
            echo "Running tests"
            break
            ;;
        "Quit")
            break
            ;;
        *) echo "Selected option '$REPLY' couldn't be find in the list of options";;
    esac
done

I have 2 questions:

  1. How can I run this script with predefined option? (For example, I want to execute this script with already selected 1st option)
  2. Is it possible to reuse one option in another option? (For example my 1st option just setting config and my 2nd option also setting the same config and after that execute install, can they be written like if option 2 selected execute 1st option and then 2nd?)

And if something written too badly, I'm open to suggestions =)

CodePudding user response:

If you put the select part in a function

main(){
  select opt in "${options[@]}"
    do
        case $opt in
            "1")
                set_config    # <--- an other funtion for option 1 to reuse it 
                break
                ;;
    .
    .
    .
}


# set a default option 
def_opt=1
# or use command line argument
def_opt="$1"

you can call main with predefined option '$def_opt' with yes

yes "$def_opt" | main 

CodePudding user response:

After digging into this and trying to do my best, I still need a little help to finish my script.

  1. Running script without any parameters are now working perfect.
  2. Passing options in that way (getopts :c:i:u:d:s:h:) leads me to an error message after executing command sh ./script.sh -c => Wrong argument 'c' provided, run sh ./scripts/collection.sh -h for help
  3. Passing options in that way (getopts "ciudsh") => working perfect, but still if I use argument that wasn't passed (ex. x) it would lead to error: Wrong argument '' provided, run sh ./scripts/collection.sh -h for help or sometimes even to this Syntax error: "(" unexpected (expecting "fi")

Please see my full script below, unfortunately for security reasons I can't post the content of the functions itself.

I would appreciate any help on fixing style, errors or anything else.

Based on your advice and other answers on stackoverflow I came up to this:

#!/usr/bin/env bash

#Colors
BRed='\033[1;31m'
Green='\033[0;32m'
BCyan='\033[1;36m'
NC='\033[0m'

f1(){
...
}
f2(){ 
...
}
f3(){
...
}
f4(){
...
}
f5(){
...
}
Help(){
    echo -e "${Green}====================================================================================================================${NC}"
    echo "You may execute the commands by selecting a number from menu or pass it as argument, see examples below:"
    echo ""
    echo -e "${Green}sh $0 ${BCyan}-argument${NC} :To execute specific command"
    echo -e "${Green}sh $0          ${NC} :To see menu with all available options"
    echo ""
    echo -e "${BCyan}   -c     ${NC}..."
    echo -e "${BCyan}   -i     ${NC}..."
    echo -e "${BCyan}   -u     ${NC}..."
    echo -e "${BCyan}   -d     ${NC}..."
    echo -e "${BCyan}   -s     ${NC}..."
    echo -e "${BCyan}   -h     ${NC}..."
    echo -e "${Green}====================================================================================================================${NC}"
    exit 1;
}

if [ $# -eq 0 ]
then
    PS3='Please enter your choice: '
    options=("1" "2" "3" "4" "5" "Help" "Quit")
    select opt in "${options[@]}"
    do
        case $opt in
            "1")
                f1;;
            "2")
                f1; f2;;
            "3")
                f1; f2;;
            "4")
                f3;;
            "5")
                f4;;
            "Help")
                Help;;
            "Quit")
                break;;
            *) echo -e "${BRed}Selected option ${BCyan}'$REPLY'${NC} ${BRed}couldn't be find in the list of provided options${NC}"
                break;;
        esac
    done
fi

while getopts :c:i:u:d:s:h: OPTION
do
        case $OPTION in
                c)
                    f1;;
                i)
                    f1; f2;;
                u)
                    f1; f3;;
                d)
                    f4;;
                s)
                    f5;;
                h)
                    Help;;
                *) echo -e "${BRed}Wrong argument ${BCyan}'$OPTARG'${NC} ${BRed}provided, run${NC} ${BCyan}sh $0 -h${NC} ${BRed}for help${NC}"
        esac
done

CodePudding user response:

How can I run this script with predefined option? (For example, I want to execute this script with already selected 1st option)

It's a bit ugly with select, move all case logic out from do ... done cycle, make your script take args and rearrange it like this:

#!/bin/bash

PS3='Please enter your choice: '
options=("1" "2" "3" "4" "Quit")

[[ $1 ]] && opt=$1 || select opt in "${options[@]}"; do break; done

case $opt in
     "1") echo "Set configuration";;
     "2") echo "Setting configuration and execution Install";;
     "3") echo "Setting configuration and execution Unlink";;
     "4") echo "Running tests";;
     "Quit") :;;
     *) echo "Selected option '$REPLY' couldn't be find in the list of options";;
esac

Is it possible to reuse one option in another option? (For example my 1st option just setting config and my 2nd option also setting the same config and after that execute install, can they be written like if option 2 selected execute 1st option and then 2nd?)

Turn the code in options into functions, this way you could easily reuse it

fun1(){ echo "Set configuration"; }
fun2(){ echo "Execution Install"; }
...

case $opt in
     "1") fun1;;
     "2") fun1; fun2;;
...

Also there are these operators for case: ;& and ;;&

man bash
...
Using ;& in place of ;; causes execution to continue with the list associated with the next set of patterns.
Using ;;& in place of ;; causes the  shell
              to  test  the next pattern list in the statement, if any, and execute any associated list on a successful match.

So if you want to make option 1 also run if option 2 selected this can be done like so:

case $opt in
     "2") fun1;&
     "1") fun1;;
...

But personally I found this method a bit tricky and hard to read.

  • Related