Comment sortir d'un script bash avec menu et sous-menu

Résolu/Fermé
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 - 19 oct. 2022 à 19:50
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 - 3 nov. 2022 à 18:46

Bonsoir,

J'ai créé un script test simplifié ( il y a normalement 5 options) pour lancer des programmes avec un menu et sous-menu. L'installation se déroule normalement. Par contre, je ne peux pas sortir du programme et la fonction suivante ne peut pas d'exécuter.

Voici le script :

#!/bin/bash
# Essai de menu et sous-menu


# Sélection de l'archive oStorybook
PS3='Faites votre choix: '
options=("oStorybook" "Exit")
select opt in "${options[@]}"
do
    if [ "$opt" == "Exit" ] ; then
       echo "Au revoir !"
       break
    fi

    case $opt in
        "oStorybook")
         PS3='Quel choix ?'
    options=("jar" "sources"  "Quit")   
    select model in "${options[@]}"
    do         
         case $model in
            "jar")
                echo "l'archive jar va s'installer"
                wget $quiet1 -nv    http://download.tuxfamily.org/ostorybook/next/oStorybook.jar
                 break ;;                                                                  
            "sources")           
                echo "Installation des sources"
                wget $quiet1 -nv http://download.tuxfamily.org/ostorybook/next/oStorybook_src-5.05.08.zip     
                break;;
            "Quit")  
             exit
            ;;   
            #*) echo "invalid option $REPLY";;                      
        esac
    done             
       
    esac
done  

# Installation de nerd-dictation (pour poursuivre l'essai)
    echo ">> Installation de nerd-dictation"
    git clone https://github.com/ideasman42/nerd-dictation.git
   

Je reviens systématiquement sur :

Quel choix ?

Qui aurait une solution ? Merci à tous.

A voir également:

12 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 20 oct. 2022 à 16:55

Bonjour,

Peux-tu encore simplifier le code de sorte à ce qu'il soit minimal, et indiquer comment l'exécuter pour mettre en évidence ton problème (comportement attendu, comportement observé) ?

Pas besoin de télécharger quoi que ce soit, juste la structure de menu, des echo aux bons endroits.

Bonne chance

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
20 oct. 2022 à 22:24

Bonsoir,

Merci pour la rapidité apportée à ta réponse !

Je te propose un script plus épuré.

#!/bin/bash 
# Essai de menu / sous-menu 

# Sélection - je n'ai laissé que deux options, la première ayant un sous-menu
PS3='Faites votre choix: '
options=("Commandes" "Exit")
select opt in "${options[@]}"
do
	if [ "$opt" == "Exit" ] ; then
    break
    fi

    case $opt in
        "Commandes")
         PS3='Quel choix ?'
	options=("pwd" "curl" "Quit")   
	select model in "${options[@]}" 
	do 		
		 case $model in
			"pwd")
				echo "pwd va s'afficher'"
				 pwd
				 break ;;
				 				 					                             
			"curl")           
				echo "curl va s'afficher"
				curl ifconfig.co/json    
				break;; 
			"Quit")  
			 exit
			;;   
		*) echo "invalid option $REPLY";;                      
		esac
	done             
     exit   
    esac
done  

# afficher la date (autre commande pour vérifier la poursuite de l'installation) 
	 
	date +"Aujourd'hui, nous sommes le %A %d %B. Il est %T." 

En fait, je désire effectuer un choix (enfin, deux !) , à deux niveaux différents :

- le 1er niveau  (menu principal), entre les deux options "Commandes" et "Exit".

- le second, une fois l'option "Commandes" choisie, un autre choix intervient  entre "pwd", "curl" et "quit".

Mon objectif est de sélectionner "Commandes" puis "pwd" par ex. pour ensuite voir la commande suivante "date..." s'exécuter.

Lors de l'exécution, le choix "Commandes" "pwd" indique bien le chemin (pwd) comme attendu. Par contre, le programme s'arrête sans exécuter la commande suivante "date...".

Si je sélectionne "Exit" au démarrage, on sort du menu et le programme affiche la commande suivante "date..." (cf. ci-dessous)

1) commandes
2) Exit
Faites votre choix: 2
Aujourd'hui, nous sommes le jeudi 20 octobre. Il est 22:08:41. C'est le 293e jour de l'année.


------------------
(program exited with code: 0)
Press return to continue

Comme tu as pu le constater, je ne suis pas un pro qui ne maîtrise pas tout. Je me suis inspiré de ce que j'ai pu glaner ici et là.

Merci.

0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
25 oct. 2022 à 15:18

Bonjour,

Pardon pour ma réponse tardive je manque de temps en ce moment. En fait il y a un problème au niveau de la structure de ton algorithme, je t'écris le structure du code en python et te laisse l'adapter en bash.

Code :

#!/usr/bin/env python3

import sys

def select(choices):
    s = None
    while s not in choices:
        for choice in choices:
            print(choice)
        s = input("type your choice: ")
    return s

def menu():
    while True:
        choice1 = select({"exit", "commande"})
        if choice1 == "exit":
            sys.exit(0)
        else:
            while True:
                choice2 = select({"pwd", "curl", "quit"})
                if choice2 == "pwd":
                    print("--> pwd")
                elif choice2 == "curl":
                    print("--> curl")
                elif choice2 == "quit":
                    break

menu()

break permet d'interrompre la boucle la plus enveloppante. Ici le premier break interrompt donc la première boucle while, et le deuxième break interrompt la 2e boucle while. Ainsi :

  • quand on choisit "exit" (première boucle) on interrompt la première boucle while et donc le programme ;
  • quand on fait "quit" (deuxième boucle), on interrompt la deuxième boucle et donc on refait un tour dans la première boucle while (ce qui revient à afficher le premier menu).

J'ai de plus défini une fonction select afin que le programme redemande à l'utilisateur de faire son choix si celui-ci n'est pas conforme à l'ensemble des valeurs valides.

Exécution :

(mando@silk) (~) $ python3 toto.py 
commande
exit
type your choice: commande
quit
pwd
curl
type your choice: pwd
--> pwd
quit
pwd
curl
type your choice: plop
quit
pwd
curl
type your choice: curl
--> curl
quit
pwd
curl
type your choice: quit
commande
exit
type your choice: exit

Bonne chance

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
26 oct. 2022 à 07:03

Bonjour,

Merci beaucoup d'avoir consacré une partie de ton temps à répondre à ma question. Je vais étudier le script en détail et l'adapter au mieux.

Bonne journée.

Cordialement.

0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
26 oct. 2022 à 10:03

Parfait, en fait je pense que dans ton cas, ligne 30, si tu remplaces exit par break ça devrait suffire (exit quitte le programme au lieu de quitter la boucle la plus enveloppante). Note par ailleurs que si tu veux suivre exactement le code que je t'ai donné, bash permet de déclarer des fonctions.

Tu peux aussi adapter le script python que je t'ai donné à tes besoins, car c'est un langage bien plus confortable que le bash. Le bash prend surtout son sens quand on veut lancer des commandes plus compliquées.

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
26 oct. 2022 à 21:42

Merci pour ces précisions. Je n'ai pas encore eu le temps de regarder attentivement !

0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 27 oct. 2022 à 10:12

Bonjour,

J'ai trouvé le temps de regarder comment écrire ton script en bash, voici à quoi ça peut ressembler :

#!/bin/bash
# Define the menu list here
PS3="> "
select opt in "Commands" "Exit"
do
    if [ "$opt" == "Exit" ] ; then
        echo "Exit"
        break
    fi

    PS3=">> "
    select subopt in "pwd" "curl" "Quit"
    do
        case "$subopt" in
            "Quit")
                echo "Quit"
                break
                ;;
            "pwd")
                echo "pwd"
                ;;
            "curl")
                echo "curl"
                ;;
        esac
    done

    PS3="> "
done

Pour s'y retrouver, tu noteras que je change à la volée l'apparence de l'invite de commande :

  • > pour le menu principal
  • >> pour le sous menu

Concernant le premier break : celui qui interrompt la boucle select opt. On arrive donc à la dernière ligne du programme et donc on quitte le script. Comme rien n'est fait après le menu, on aurait aussi pu écrire exit 0, ce qui quitte immédiatement le programme.

Concernant le second break : celui qui interrompt la boucle select subopt. Si on voulait quitter le programme avec cette option, il faudrait le remplacer par exit 0.

Exemple :

1) Commands
2) Exit
> 1
1) pwd
2) curl
3) Quit
>> 1
pwd
>> 1
pwd
>> 2
curl
>> 3
Quit
> 2
Exit

Bonne chance

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
28 oct. 2022 à 12:57

Merci pour ta démonstration très claire. La difficulté que je rencontre consiste à poursuivre l'exécution des commandes. Si tu regardes bien, je précisais dans mon premier message qu'après le choix effectué, l'exécution devait se poursuivre avec autre commande :

# afficher la date (autre commande pour vérifier la poursuite de l'installation) 
	 
	date +"Aujourd'hui, nous sommes le %A %d %B. Il est %T." 

C'est à ce niveau que le programme bloquait. Cette commande n'était lue qu'en cas de sortie de la partie du script traitant du choix. 

1) Commands
2) Exit
> 2
Exit
Aujourd'hui, nous sommes le vendredi 28 octobre. Il est 12:55:44.


------------------
(program exited with code: 0)
Press return to continue

J'ignore s'il est possible de traiter cette commande dans le script.

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
31 oct. 2022 à 14:53

Bonjour,

J'ai résolu la question en adaptant un script trouvé sur le Net proposant menu et sous-menu.  Voici une version simplifiée. Si elle peut être utile à certains néophytes comme moi, tant mieux !

Encore merci.

#!/bin/bash
# Script avec menu et sous-menu
while :
do
echo "
----- SELECT  -----

(1)  A
(2)  B
(3)  Q = Quitter
"

read choix_
case $choix  in
 1) echo " -----sous-menu 1-----

    1)  A1
    2)  A2
    3)  Q = Quitter
    "
    read choix sous-menu 1
    echo
    case $choix sous-menu 1 in
    1) echo "vous avez sélectionné A1 "
    commande A1 ;;
    2) echo "vous avez sélectionné A2 "
    commande A2;;
    3| Q | q ) echo ; exit 0 ;;
    *) echo "Erreur saisie sous-menu 1";;
    esac
    ;;

 2) echo " -----sous-menu 2-----

    1)  B1
    2)  B2
    3)  Q = Quitter
    "
    read choix sous-menu 2
    echo
    case $choix sous-menu 2 in
    1) echo "vous avez sélectionné B1 "
    commande B1;;
    2) echo "vous avez sélectionné B2 "
    commande B2;;
    3| Q | q ) echo ; exit 0 ;;
    *) echo "Erreur saisie sous-menu 2";;
    esac
    ;;

3) | Q | q ) echo ; exit 0
;;

*) echo "Erreur saisi menu principal"
;;
	esac
done
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
2 nov. 2022 à 15:06

Bonjour,

Concernant ton message #8, je n'ai pas compris : la commande date s'exécute quand tu rencontres la commande (au même titre que les echo que j'ai mis en exemple), mais j'imagine que tu as depuis contourné le problème. En tout cas l'idée est toujours la même que dans mon message #7 : la manière dont sont imbriqués les sous-menus est reflétée par la manière dont sont imbriqués les select.

Voilà à quoi ça pourrait ressembler :

#!/bin/bash
# Define the menu list here
PS3="> "
select opt in "A" "B" "Exit"
do
    case "$opt" in
    "Exit")
        echo "Exit"
        break
        ;;
    "A")
        PS3=">> "
        select subopt in "Quit" "A1" "A2"
        do
            case "$subopt" in
                "Quit")
                    echo "Quit"
                    break
                    ;;
                "A1")
                    echo "A1"
                    ;;
                "A2")
                    echo "A2"
                    ;;
            esac
        done
        ;;
    "B")
        PS3=">> "
        select subopt in "Quit" "B1" "B2"
        do
            case "$subopt" in
                "Quit")
                    echo "Quit"
                    break
                    ;;
                "B1")
                    echo "B1"
                    ;;
                "B2")
                    echo "B2"
                    ;;
            esac
        done
        ;;

    esac
    PS3="> "
done

Exécution :

(mando@silk) (~) $ bash toto.sh 
1) A
2) B
3) Exit
> 1
1) Quit
2) A1
3) A2
A> 3
A2
A> 2
A1
A> 1
Quit
> 2
1) Quit
2) B1
3) B2
B> 2
B1
B> 3
B2
B> 1
Quit
> 3
Exit

Concernant ton message #9, c'est une manière plus basique de faire. Contrairement à celle que je viens de proposer; elle n'utilise pas select, donc elle s'applique à des shells autre que bash.

Bonne chance

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
3 nov. 2022 à 07:07

Merci. je comprends bien la structure du script. Par contre, je n'ai toujours pas compris comment ajouter une commande pour poursuivre le script une fois le choix effectué.

Pour illustrer mon propos, voici ce qui a motivé mes messages :

Je contribue au développement (porteur d'idées, testeur et accessoirement "codeur !)) de oStorybook.

Ayant découvert un programme de Speech to text (nerd-dictation), j'ai proposé d'intégrer ce logiciel dans oStorybook, non pas pour écrire des livres "à la volée" mais pour faciliter la prise de notes, les remarques, etc. Une précision. Une fois lancé, ce programme tourne en tâche de fond et envoie les mots reconnus dans l'application qui est active (courrier, traitement de texte, console, etc)

A l'occasion, je me suis attelé avec le développeur principal à la réalisation du script pour automatiser l'installation.

Le script d'installation lit et exécute les différentes commandes : définition des répertoires d'installation, dépendances, etc. Viennent ensuite la choix de la langue et du modèle linguistique "léger" ou "complet". C'est cette phase qui me posait problème et que j'ai traitée d'une manière détournée (cf #8) avec car, une fois les choix effectués, le programme ne se poursuivait pas. D'où la simulation avec la commande "date" dans mes messages.

Concrètement, j'ai ajouté la commande "whoami" à la fin de ton dernier script, après Exit. La sortie ne m'a pas étonné, la commande reste ignorée. C'est cette difficulté  sûrement très triviale que je voulais résoudre. Et comme je suis curieux de nature...

J'ai finalement trouvé un moyen détourné pour réaliser le script qui fonctionne.

Encore merci pour ta disponibilité.

0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
3 nov. 2022 à 11:49

Par contre, je n'ai toujours pas compris comment ajouter une commande pour poursuivre le script une fois le choix effectué.

Peux-tu clarifier ? Si je reprends le message #10, si tu choisis Exit, comme maintenant j'ai mis un break (au lieu de exit), cela te fait poursuivre le programme ligne 51 (au lieu de quitter le script).

Ayant découvert un programme de Speech to text (nerd-dictation), j'ai proposé d'intégrer ce logiciel dans oStorybook, non pas pour écrire des livres "à la volée" mais pour faciliter la prise de notes, les remarques, etc. Une précision. Une fois lancé, ce programme tourne en tâche de fond et envoie les mots reconnus dans l'application qui est active (courrier, traitement de texte, console, etc)

Pourquoi pas, mais de tels outils existent déjà. Par exemple, dans les hôpitaux, certains docteurs ont une espèce de micro qui leur permettent de remplir les dossiers. Ils dictent également les ponctuations et les retours à la lignes, et font quelques corrections mineures au clavier. Cette page recense quelques outils analogues sous Linux. Peut-être qu'il vaut mieux consacrer son énergie à contribuer à un projet existant (pour l'améliorer) plutôt que re-développer quelque chose qui a déjà été fait, à bon entendeur ;-)

Afin de consacrer un fil de discussion par sujet, si tu veux plus de détails, merci d'ouvrir un nouveau fil de discussion.

Concrètement, j'ai ajouté la commande "whoami" à la fin de ton dernier script, après Exit. La sortie ne m'a pas étonné, la commande reste ignorée. C'est cette difficulté  sûrement très triviale que je voulais résoudre. Et comme je suis curieux de nature...

Si tu as bien recopié le script #10 et ajouté ligne 51 la commande whoami, normalement ça fait ce que tu veux.

1) A
2) B
3) Exit
> 3
Exit
mando

Si j'ai mal compris ce que tu veux faire, merci de clarifier.

Bonne chance

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
Modifié le 3 nov. 2022 à 17:04

Il ne s'agit nullement de ré-développer un programme existant mais de l'adapter, ce qui est bien différent. Le projet nerd-dictation est disponible sur Github. Combien d'utilisateurs de l'outil informatique connaissent ce site et combien seraient capables de récupérer l'archive, de l'installer, d'installer les dépendances et de configurer le fichier linguistique ? C'est ce que nous faisons actuellement pour proposer une fonctionnalité opérationnelle ne nécessitant aucune manipulation de la part des utilisateurs.

C'est également ce qu'a fait Papoteur qui a écrit un GUI pour nerd-dictation, Elograf qui malheureusement ne fonctionne pas sur toutes les distros ( Ubuntu Mate en fait partie).

0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
3 nov. 2022 à 17:52

Ah très bien, je ne connaissais pas mais effectivement si c'est l'adapter, c'est parfait !

Quelques pistes pour le packaging : le projet nerd-dictation dispose d'un setup.py, ce qui signifie que le paquet est plus ou moins prêt à être packagé sur Pypi (tous les OS), en rpm (distributions basées sur redhat) ou en deb (distributions basées sur debian). Si ton projet dépend de nerd-dictation et d'autres projets, tu peux tout à fait faire ton propre paquet avec ses propres dépendances. Pour plus de détails, voir ce tutoriel.

0
Lume_56 Messages postés 26 Date d'inscription lundi 1 juin 2020 Statut Membre Dernière intervention 20 octobre 2023 1
3 nov. 2022 à 18:46

Merci pour ces pistes. Le packaging est à l'état de projet car il reste d'autres points à développer.

0