Comment créer un menu de sélection dans un script shell?

99

Je crée un script bash simple et je veux créer un menu de sélection, comme ceci:

$./script

echo "Choose your option:"

1) Option 1  
2) Option 2  
3) Option 3  
4) Quit  

Et selon le choix de l’utilisateur, je souhaite que différentes actions soient exécutées. Je suis un scripteur de shell bash, j'ai cherché quelques réponses sur le Web, mais je n'ai rien de concret.

    
posée Daniel Rodrigues 08.08.2010 - 23:49
la source

11 réponses

109
#!/bin/bash
# Bash Menu Script Example

PS3='Please enter your choice: '
options=("Option 1" "Option 2" "Option 3" "Quit")
select opt in "${options[@]}"
do
    case $opt in
        "Option 1")
            echo "you chose choice 1"
            ;;
        "Option 2")
            echo "you chose choice 2"
            ;;
        "Option 3")
            echo "you chose choice $REPLY which is $opt"
            ;;
        "Quit")
            break
            ;;
        *) echo "invalid option $REPLY";;
    esac
done

Ajoutez les instructions break à la sortie de la boucle select . Si break n'est pas exécuté, l'instruction select effectue une boucle et le menu est ré-affiché.

Dans la troisième option, j'ai inclus des variables définies par l'instruction select pour démontrer que vous avez accès à ces valeurs. Si vous le choisissez, il affichera:

you chose choice 3 which is Option 3

Vous pouvez voir que $REPLY contient la chaîne que vous avez entrée à l'invite. Il est utilisé comme index dans le tableau ${options[@]} comme si le tableau était basé sur 1. La variable $opt contient la chaîne de cet index dans le tableau.

Notez que les choix peuvent être une simple liste directement dans l'instruction select comme ceci:

select opt in foo bar baz 'multi word choice'

mais vous ne pouvez pas mettre une telle liste dans une variable scalaire à cause des espaces dans l’un des choix.

Vous pouvez également utiliser le regroupement de fichiers si vous choisissez parmi les fichiers:

select file in *.tar.gz
    
réponse donnée Dennis Williamson 09.08.2010 - 01:41
la source
49

Pas une nouvelle réponse en soi , mais comme il n’ya pas encore de réponse acceptée, voici quelques astuces de codage, à la fois pour select et zenity:

title="Select example"
prompt="Pick an option:"
options=("A" "B" "C")

echo "$title"
PS3="$prompt "
select opt in "${options[@]}" "Quit"; do 

    case "$REPLY" in

    1 ) echo "You picked $opt which is option $REPLY";;
    2 ) echo "You picked $opt which is option $REPLY";;
    3 ) echo "You picked $opt which is option $REPLY";;

    $(( ${#options[@]}+1 )) ) echo "Goodbye!"; break;;
    *) echo "Invalid option. Try another one.";continue;;

    esac

done

while opt=$(zenity --title="$title" --text="$prompt" --list \
                   --column="Options" "${options[@]}"); do

    case "$opt" in
    "${options[0]}" ) zenity --info --text="You picked $opt, option 1";;
    "${options[1]}" ) zenity --info --text="You picked $opt, option 2";;
    "${options[2]}" ) zenity --info --text="You picked $opt, option 3";;
    *) zenity --error --text="Invalid option. Try another one.";;
    esac

done

À noter:

  • Les deux vont boucler jusqu'à ce que l'utilisateur choisisse explicitement Quitter (ou Annuler pour le zénity). C'est une bonne approche pour les menus de script interactif: après avoir sélectionné un choix et effectué une action, le menu est présenté à nouveau pour un autre choix. Si le choix ne se veut qu'une seule fois, utilisez simplement break après esac (l'approche de zénité pourrait être encore réduite)

  • Les deux case sont basés sur des index plutôt que sur des valeurs. Je pense que c'est plus facile à coder et à maintenir

  • Le tableau est également utilisé pour l'approche zenity .

  • L'option "Quit" ne fait pas partie des options initiales. Il est "ajouté" si nécessaire, afin que votre tableau reste propre. Après tout, "Quitter" n'est de toute façon pas nécessaire pour le zenity, l'utilisateur peut simplement cliquer sur "Annuler" (ou fermer la fenêtre) pour quitter. Remarquez comment les deux utilisent le même tableau d’options intact.

  • PS3 et REPLY vars peuvent être non renommés. select est codé pour les utiliser. Toutes les autres variables du script (opt, options, prompt, title) peuvent avoir n'importe quel nom, à condition que vous fassiez les ajustements

réponse donnée MestreLion 05.08.2011 - 09:40
la source
34

En utilisant dialog , la commande devrait ressembler à ceci:

dialog --clear --backtitle "Backtitle here" --title "Title here" --menu "Choose one of the following options:" 15 40 4 \
1 "Option 1" \
2 "Option 2" \
3 "Option 3"

Le mettre dans un script:

#!/bin/bash

HEIGHT=15
WIDTH=40
CHOICE_HEIGHT=4
BACKTITLE="Backtitle here"
TITLE="Title here"
MENU="Choose one of the following options:"

OPTIONS=(1 "Option 1"
         2 "Option 2"
         3 "Option 3")

CHOICE=$(dialog --clear \
                --backtitle "$BACKTITLE" \
                --title "$TITLE" \
                --menu "$MENU" \
                $HEIGHT $WIDTH $CHOICE_HEIGHT \
                "${OPTIONS[@]}" \
                2>&1 >/dev/tty)

clear
case $CHOICE in
        1)
            echo "You chose Option 1"
            ;;
        2)
            echo "You chose Option 2"
            ;;
        3)
            echo "You chose Option 3"
            ;;
esac
    
réponse donnée Alaa Ali 26.08.2015 - 21:33
la source
13

Vous pouvez utiliser ce script simple pour créer des options

#!/bin/bash
echo "select the operation ************  1)operation 1 2)operation 2 3)operation 3 4)operation 4 "

read n
case $n in
    1) commands for opn 1;;
    2) commands for opn 2;;
    3) commands for opn 3;;
    4) commands for  opn 4;;
    *) invalid option;;
esac
    
réponse donnée jibin 11.08.2011 - 14:11
la source
7

Comme ceci est destiné à Ubuntu, vous devez utiliser le backend que debconf est configuré pour utiliser. Vous pouvez trouver le backend debconf avec:

sudo -s "echo get debconf/frontend | debconf-communicate"

S'il dit "dialog", il utilise probablement whiptail ou dialog . Sur Lucid, c'est whiptail .

Si cela échoue, utilisez bash "select" comme expliqué par Dennis Williamson.

    
réponse donnée Li Lo 10.08.2010 - 02:30
la source
6

J'ai utilisé Zenity, qui semble toujours là dans Ubuntu, fonctionne très bien et possède de nombreuses fonctionnalités. Ceci est une esquisse d'un menu possible:

#! /bin/bash

selection=$(zenity --list "Option 1" "Option 2" "Option 3" --column="" --text="Text above column(s)" --title="My menu")

case "$selection" in
"Option 1")zenity --info --text="Do something here for No1";;
"Option 2")zenity --info --text="Do something here for No2";;
"Option 3")zenity --info --text="Do something here for No3";;
esac
    
réponse donnée LazyEchidna 05.05.2011 - 03:28
la source
6
#!/bin/sh
show_menu(){
    NORMAL='echo "3[m"'
    MENU='echo "3[36m"' #Blue
    NUMBER='echo "3[33m"' #yellow
    FGRED='echo "3[41m"'
    RED_TEXT='echo "3[31m"'
    ENTER_LINE='echo "3[33m"'
    echo -e "${MENU}*********************************************${NORMAL}"
    echo -e "${MENU}**${NUMBER} 1)${MENU} Mount dropbox ${NORMAL}"
    echo -e "${MENU}**${NUMBER} 2)${MENU} Mount USB 500 Gig Drive ${NORMAL}"
    echo -e "${MENU}**${NUMBER} 3)${MENU} Restart Apache ${NORMAL}"
    echo -e "${MENU}**${NUMBER} 4)${MENU} ssh Frost TomCat Server ${NORMAL}"
    echo -e "${MENU}**${NUMBER} 5)${MENU} ${NORMAL}"
    echo -e "${MENU}*********************************************${NORMAL}"
    echo -e "${ENTER_LINE}Please enter a menu option and enter or ${RED_TEXT}enter to exit. ${NORMAL}"
    read opt
}
function option_picked() {
    COLOR='3[01;31m' # bold red
    RESET='3[00;00m' # normal white
    MESSAGE=${@:-"${RESET}Error: No message passed"}
    echo -e "${COLOR}${MESSAGE}${RESET}"
}

clear
show_menu
while [ opt != '' ]
    do
    if [[ $opt = "" ]]; then 
            exit;
    else
        case $opt in
        1) clear;
        option_picked "Option 1 Picked";
        sudo mount /dev/sdh1 /mnt/DropBox/; #The 3 terabyte
        menu;
        ;;

        2) clear;
            option_picked "Option 2 Picked";
            sudo mount /dev/sdi1 /mnt/usbDrive; #The 500 gig drive
        menu;
            ;;

        3) clear;
            option_picked "Option 3 Picked";
        sudo service apache2 restart;
            show_menu;
            ;;

        4) clear;
            option_picked "Option 4 Picked";
        ssh [email protected] -p 2010;
            show_menu;
            ;;

        x)exit;
        ;;

        \n)exit;
        ;;

        *)clear;
        option_picked "Pick an option from the menu";
        show_menu;
        ;;
    esac
fi
done
    
réponse donnée Alex Lucard 18.02.2013 - 15:29
la source
4

Bash fancy menu

Essayez-le d'abord, puis visitez ma page pour une description détaillée ... Pas besoin de bibliothèques externes ou de programmes tels que dialogues ou zenity ...

#/bin/bash
# by oToGamez
# www.pro-toolz.net

      E='echo -e';e='echo -en';trap "R;exit" 2
    ESC=$( $e "\e")
   TPUT(){ $e "\e[;H";}
  CLEAR(){ $e "\ec";}
  CIVIS(){ $e "\e[?25l";}
   DRAW(){ $e "\e%@\e(0";}
  WRITE(){ $e "\e(B";}
   MARK(){ $e "\e[7m";}
 UNMARK(){ $e "\e[27m";}
      R(){ CLEAR ;stty sane;$e "\ec\e[37;44m\e[J";};
   HEAD(){ DRAW
           for each in $(seq 1 13);do
           $E "   x                                          x"
           done
           WRITE;MARK;TPUT 1 5
           $E "BASH SELECTION MENU                       ";UNMARK;}
           i=0; CLEAR; CIVIS;NULL=/dev/null
   FOOT(){ MARK;TPUT 13 5
           printf "ENTER - SELECT,NEXT                       ";UNMARK;}
  ARROW(){ read -s -n3 key 2>/dev/null >&2
           if [[ $key = $ESC[A ]];then echo up;fi
           if [[ $key = $ESC[B ]];then echo dn;fi;}
     M0(){ TPUT  4 20; $e "Login info";}
     M1(){ TPUT  5 20; $e "Network";}
     M2(){ TPUT  6 20; $e "Disk";}
     M3(){ TPUT  7 20; $e "Routing";}
     M4(){ TPUT  8 20; $e "Time";}
     M5(){ TPUT  9 20; $e "ABOUT  ";}
     M6(){ TPUT 10 20; $e "EXIT   ";}
      LM=6
   MENU(){ for each in $(seq 0 $LM);do M${each};done;}
    POS(){ if [[ $cur == up ]];then ((i--));fi
           if [[ $cur == dn ]];then ((i++));fi
           if [[ $i -lt 0   ]];then i=$LM;fi
           if [[ $i -gt $LM ]];then i=0;fi;}
REFRESH(){ after=$((i+1)); before=$((i-1))
           if [[ $before -lt 0  ]];then before=$LM;fi
           if [[ $after -gt $LM ]];then after=0;fi
           if [[ $j -lt $i      ]];then UNMARK;M$before;else UNMARK;M$after;fi
           if [[ $after -eq 0 ]] || [ $before -eq $LM ];then
           UNMARK; M$before; M$after;fi;j=$i;UNMARK;M$before;M$after;}
   INIT(){ R;HEAD;FOOT;MENU;}
     SC(){ REFRESH;MARK;$S;$b;cur='ARROW';}
     ES(){ MARK;$e "ENTER = main menu ";$b;read;INIT;};INIT
  while [[ "$O" != " " ]]; do case $i in
        0) S=M0;SC;if [[ $cur == "" ]];then R;$e "\n$(w        )\n";ES;fi;;
        1) S=M1;SC;if [[ $cur == "" ]];then R;$e "\n$(ifconfig )\n";ES;fi;;
        2) S=M2;SC;if [[ $cur == "" ]];then R;$e "\n$(df -h    )\n";ES;fi;;
        3) S=M3;SC;if [[ $cur == "" ]];then R;$e "\n$(route -n )\n";ES;fi;;
        4) S=M4;SC;if [[ $cur == "" ]];then R;$e "\n$(date     )\n";ES;fi;;
        5) S=M5;SC;if [[ $cur == "" ]];then R;$e "\n$($e by oTo)\n";ES;fi;;
        6) S=M6;SC;if [[ $cur == "" ]];then R;exit 0;fi;;
 esac;POS;done
    
réponse donnée user360154 19.12.2014 - 10:15
la source
4

J'ai une autre option qui est un mélange de ces réponses, mais ce qui le rend intéressant, c’est que vous n’avez besoin que d’appuyer sur une touche, puis le script continue grâce à l’option -n de read. Dans cet exemple, nous demandons d’arrêter, de redémarrer ou de quitter simplement scrit en utilisant ANS comme variable et il suffit à l’utilisateur d’appuyer sur E, R ou S. Je configure également la sortie par défaut. alors le script va sortir.

read -n 1 -p "Would you like to exit, reboot, or shutdown? (E/r/s) " ans;

case $ans in
    r|R)
        sudo reboot;;
    s|S)
        sudo poweroff;;
    *)
        exit;;
esac
    
réponse donnée HarlemSquirrel 17.05.2015 - 05:58
la source
2

Vous avez déjà répondu à la même question dans serverfault . La solution utilisée ici est Whiptail .

    
réponse donnée txwikinger 08.08.2010 - 23:56
la source
-1

En supposant que vous souhaitiez utiliser un menu de script shell simple (sans interface utilisateur sophistiquée), consultez l'exemple de menu à partir de lien .

    
réponse donnée João Pinto 09.08.2010 - 00:35
la source

Lire d'autres questions sur les étiquettes