Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 08/03/2021, à 17:59

Tawal

[Résolu] Script - Options courtes et Arguments

Hello,

J'ai un script (projet) qui peut prendre 2 options (courtes) sans valeur et DOIT avoir 3 arguments dans sa ligne de commande.

J'ai écrit (en me renseignant un peu à l'avance) cette séquence pour gérer les options et les arguments.
Ça fonctionne, mais est-ce une bonne méthode ?
Et y a-t-il des erreurs ou des "grossièretés" ?
Peut-on faire mieux ? (j'en doute même pas lol)

usage() {
    echo "Usage ..........."
}


while getopts :hr opt
do
    case $opt in
        h ) opt_h="$opt" ;;
        r ) opt_r="$opt" ;;
        * ) usage cas $OPTARG
            exit 0 ;;
    esac
done


shift $(($OPTIND-1))


[ ! "$#" -eq 3 ] && {
    usage arg
    exit 0
}

En vous remerciant de vos conseils, critiques et autres renvois à la "doc" big_smile

Au plaisir.

Dernière modification par Tawal (Le 11/03/2021, à 18:43)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#2 Le 08/03/2021, à 18:24

beuguissime

Re : [Résolu] Script - Options courtes et Arguments

Salut,

Si l'option -h affiche l'aide, alors je dirai que ta fonction usage et un exit doivent être exécutés sous le “case h)”.
Le shift doit être sous le “case r)”.

while getopts :hr opt
do
    case $opt in
        h) 
            #opt_h="$opt"      # Plus nécessaire ? Sauf si j'ai mal interprété le sens de l'option -h
            usage
            exit 0
            ;;
        r)
            opt_r="$opt"
            ;;
        *) 
            usage cas $OPTARG
            exit 1
            ;;
    esac
done

Modification : correction d'un des deux exit et de la remarque sur le shift

Dernière modification par beuguissime (Le 08/03/2021, à 18:56)

Hors ligne

#3 Le 08/03/2021, à 18:40

Tawal

Re : [Résolu] Script - Options courtes et Arguments

Merci de ta réponse.

beuguissime a écrit :

# Plus nécessaire ? Sauf si j'ai mal interprété le sens de l'option -h

Très bonne interprétation wink
Oui, c'est ainsi que je pensais traiter ce cas,
J'ai donné le code de mes tests (j'ai pas mis les echo de contrôle)

Ensuite, je vois la correction des exit, je pensais aussi afficher l'usage sur stderr : raison ou pas ?

Par contre, la position du shift me chiffonne un peu.
J'ai pas testé ton code, mais il me semble qu'ainsi on perd la possibilité de concaténer les options (-rh [inutile ici tu vas me dire]).
Me -trompe-je ? big_smile
Sinon, pourquoi le "faudrait-il" sous le case r) ?

Au plaisir.


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#4 Le 08/03/2021, à 18:48

beuguissime

Re : [Résolu] Script - Options courtes et Arguments

J'avoue ne plus avoir joué avec getopts dans un script bash depuis un certain temps. Il me semble que je faisais des choses de ce genre.

Quand je disais “sous le case x)”, je voulais dire de façon elliptique que c'était une action à faire quand le programme tombe dans le cas x, directement à l'intérieur du ”case x)” et non à l'extérieur… surtout pour des actions simples (afficher l'aide) qui se terminent par un exit. Pas besoin d'aller plus loin dans l'interprétation du script. Effectivement, j'ai pris l'habitude d'écrire en-dessous le “x)” (au sens typographique, désolé de la confusion).

Pour les exit 1, tu peux revenir au exit 0 si tu veux. Dans ma mémoire, il me semble que j'avais noté que certaines commandes sortaient un code 1 quand on affichait l'aide. Je viens de tester avec git --help ou mv --help, ça retourne 0. Idem pour l'affiche de l'aide sur stdout ou stderr. Je ne suis pas sûr que ce soit formalisé.


Ajout : oui, je me suis planté pour le shift, mille excuses. Il est très bien là où il est. wink

Dernière modification par beuguissime (Le 08/03/2021, à 19:05)

Hors ligne

#5 Le 08/03/2021, à 19:56

MicP

Re : [Résolu] Script - Options courtes et Arguments

Bonjour

J'avais joué un bon moment avec la commande getops
et j'ai beaucoup apprécié ce tuto, les liens que j'y ai trouvé et le fil de discussion qu'on y trouve en fin de page.

Dernière modification par MicP (Le 08/03/2021, à 19:59)

Hors ligne

#6 Le 08/03/2021, à 19:58

kamaris

Re : [Résolu] Script - Options courtes et Arguments

beuguissime a écrit :

Pour les exit 1, tu peux revenir au exit 0 si tu veux. Dans ma mémoire, il me semble que j'avais noté que certaines commandes sortaient un code 1 quand on affichait l'aide. Je viens de tester avec git --help ou mv --help, ça retourne 0.

git --help retourne 0, puisque le programme peut faire ce qu'on lui a demandé et se termine comme attendu, mais par exemple

$ git --fausse-option
option inconnue : --fausse-option
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]
$ echo $?
129
$

Donc je trouve que ce que tu as mis en #2 est bien.
Pour stdout/stderr, je suivrais la même logique : sur stdout pour --help, sur stderr pour une mauvaise option (ce que fait d'ailleurs git).

Dernière modification par kamaris (Le 08/03/2021, à 19:58)

Hors ligne

#7 Le 08/03/2021, à 20:08

beuguissime

Re : [Résolu] Script - Options courtes et Arguments

Oui, après réflexion, j'ai du confondre 2 cas :

* le cas où usage est affiché car option -h ou --help -> exit 0
* le cas où usage est affiché car syntaxe incorrecte -> exit 1

J'ai donc corrigé plus tôt ma suggestion au message #2 pour refléter ce comportement : un exit 0 dans un cas, un exit 1 dans l'autre.

Je suis d'accord avec ta suggestion pour la sortie sur stdout ou stderr. Si l'affichage de l'aide est explicitement demandé, ça devrait être sur stdout puisque c'est le comportement normal. Si l'affichage d'un (mini-)message d'aide résulte d'une erreur, ça doit aller sur stderr.

Hors ligne

#8 Le 08/03/2021, à 21:08

Tawal

Re : [Résolu] Script - Options courtes et Arguments

Super smile

Donc je retiens :

  • un exit 0 pour la demande -h et un exit 1 (ou autre) pour les mauvaises options.

  • une redirection sur stderr qu'en cas de mauvaises options

  • La position du shift reste après la boucle while

Thanks a lot.

Edit: je confirme vos dires, c'est bien le comportement par défaut :

$ bash --mauvaise_option > log
bash: --mauvaise_option : option non valable
Utilisation :	bash [option longue GNU] [option] ...
	bash [option longue GNU] [option] fichier-script ...
Options longues GNU :
	--debug
	--debugger
	--dump-po-strings
	--dump-strings
	--help
	--init-file
	--login
	--noediting
	--noprofile
	--norc
	--posix
	--pretty-print
	--rcfile
	--restricted
	--verbose
	--version
Options du shell :
	-ilrsD ou -c commande ou -O shopt_option		(invocation seulement)
	-abefhkmnptuvxBCHP ou -o option
$ cat log
$ bash --mauvaise_option 2> log
$ cat log
bash: --mauvaise_option : option non valable
Utilisation :	bash [option longue GNU] [option] ...
	bash [option longue GNU] [option] fichier-script ...
Options longues GNU :
	--debug
	--debugger
	--dump-po-strings
	--dump-strings
	--help
	--init-file
	--login
	--noediting
	--noprofile
	--norc
	--posix
	--pretty-print
	--rcfile
	--restricted
	--verbose
	--version
Options du shell :
	-ilrsD ou -c commande ou -O shopt_option		(invocation seulement)
	-abefhkmnptuvxBCHP ou -o option
$

@MicP : Merci pour le lien wink

Dernière modification par Tawal (Le 08/03/2021, à 21:20)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#9 Le 08/03/2021, à 23:57

Tawal

Re : [Résolu] Script - Options courtes et Arguments

Re,

Du coup, après renseignement (lecture merci MicP), j'ai fait comme ceci :

while getopts :hr-: opt
do
    case $opt in
        h) usage
           exit 0
           ;;
        r) opt_r="OK"
           ;;
        -) case $OPTARG in
                   help) usage
                         exit 0
                         ;;
               recursif) opt_r="OK"
                         ;;
                      *) usage cas $OPTARG 1>&2
                         exit 1
                         ;;
           esac
           ;; 
        *) usage cas $OPTARG 1>&2
           exit 1
           ;;
    esac
done

shift $(($OPTIND-1))

Je laisse, pour l'instant, les exit 1, c'est à peaufiner le code retour.
Surtout, ça gère les options longues (cas facile, option sans valeur).

Moi, ça me plaît.
Qu'en pensez-vous ?

Edit: hmmmm, je vois une faiblesse, je teste ....

Dernière modification par Tawal (Le 09/03/2021, à 00:01)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#10 Le 09/03/2021, à 00:15

kamaris

Re : [Résolu] Script - Options courtes et Arguments

Tu as regardé getopt aussi ? (sans s à la fin)
C'est une commande externe qui fait plus de boulot, en particulier un préfiltre qui sort en code erreur 1 sur stderr en cas d'option invalide, et qui t'assure d'avoir les options formatées selon les conventions GNU, en terminant la liste par --, etc.
Perso je préfère utiliser ça, mais j'avoue que ça fait un moment que je n'y ai pas touché…

Hors ligne

#11 Le 09/03/2021, à 00:36

Tawal

Re : [Résolu] Script - Options courtes et Arguments

kamaris a écrit :

Tu as regardé getopt aussi

Oui, mais je préfère rester en built-in.
Après, pour un bon lot d'options (courtes et longues), getopt est peut-être plus adapté.
Mais pour 2-3 options, autant utiliser la primitive du shell, je pense.


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#12 Le 09/03/2021, à 00:50

beuguissime

Re : [Résolu] Script - Options courtes et Arguments

Marrant, j'ai toujours lu qu'il fallait préférer getopts à getopt.

Hors ligne

#13 Le 09/03/2021, à 01:41

kamaris

Re : [Résolu] Script - Options courtes et Arguments

Oui, j'ai souvent lu ça aussi, mais rarement argumenté, si ce n'est de vouloir utiliser une primitive du shell, ce qui est effectivement recevable.

Hors ligne

#14 Le 09/03/2021, à 01:51

beuguissime

Re : [Résolu] Script - Options courtes et Arguments

À l'époque où j'avais beaucoup joué avec getopt/getopts, j'en avais conclu que le conseil de préférer getopts était plutôt fondé (du moins pour mes usages/besoins)… mais je ne peux pas redire aujourd'hui pourquoi. Depuis, je fais plutôt du argparse en python.

Hors ligne

#15 Le 09/03/2021, à 09:25

Tawal

Re : [Résolu] Script - Options courtes et Arguments

En fait, j'ai tendance à croire que Bash n'est pas trop approprié pour "parser" correctement et simplement des options courtes et longues ...

Dernière modification par Tawal (Le 09/03/2021, à 09:25)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#16 Le 09/03/2021, à 10:02

Hizoka

Re : [Résolu] Script - Options courtes et Arguments

Salut, perso j'utilise mon propre systeme :

unset StopOptions

while [[ ${*} ]]
do
    # Options indiquant que la suite ne contient plus d'option
    # Avec ce système, on peut utiliser -- comme argument : commande ... -- dqsdsq -- dsqdsq => le 2e -- est un argument et non à nouveau un indicateur d’arrêt des options
    if [[ -z ${StopOptions} && "${1}" == "--" ]]
    then
        StopOptions=1
        shift
        continue
    fi

    # Si on a pas indiqué que les options sont terminées
    if (( ! StopOptions ))
    then
        unset Options Temp

        # Si c'est une option longue
        if [[ "${1}" == "--"* ]]
        then
            Options=("${1/#--}")

        # Si c'est une option courte ou plusieurs options courtes concaténées
        elif [[ "${1}" == "-"* ]]
        then
            Temp="${1/#-}"
            [[ ${Temp} =~ ${Temp//?/(.)} ]] && Options=("${BASH_REMATCH[@]:1}")

        # Si c'est un argument
        else
            echo "${1} est un argument"
        fi

        # Traitement des options
        for Option in "${Options[@]}"
        do
            case "${Option}" in
                h|help) echo "Help me !" ;;

                a|all) echo "option all" ;;

                s|special)
                    # Si cette option nécessite une valeur, on la recherche
                    # Cette option doit être la dernière de la liste car elle attend une valeur
                    if [[ "${Option}" != "${Options[-1]}" || "${2-vide}" == "vide" ]]
                    then
                        echo "l'option ${Option} nécessite une valeur !"

                    else
                        # Récupération de la valeur même vide
                        ValeurOption="${2}"

                        # On déplace les arguments d'1
                        shift

                        echo "L'option ${Option} a pour valeur ${ValeurOption}"
                    fi ;;

                *) echo "${Option} n'est pas une option valide !";;
            esac
        done

    # Si ce ne sont plus des options, ce sont des arguments
    else
        echo "${1} est un argument post --"
    fi

    # On déplace les arguments d'1
    shift
done

Il prend en compte les options longues et courtes avec ou sans argument, il accepte la concaténation des options courtes et il accepte également les arguments de commande hors option.


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#17 Le 09/03/2021, à 11:39

Tawal

Re : [Résolu] Script - Options courtes et Arguments

Hello,

Si je comprends bien ton code, on pourrait gérer ce genre de situation :

script -r    Doss1    Doss2    Doss3    -r     Doss4    Doss5
#    option  valeur    arg1    arg2   option   valeur    arg3

là, où getopts arrêterait sa recherche d'option au plus tard sur Doss2. Et la prochaine occurrence de "-r" serait interprétée comme un argument positionnel par getopts.

Dernière modification par Tawal (Le 09/03/2021, à 11:42)


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne

#18 Le 09/03/2021, à 13:56

Hizoka

Re : [Résolu] Script - Options courtes et Arguments

En toute logique tu peux tout faire dont ce que tu proposes smile


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#19 Le 09/03/2021, à 19:32

kamaris

Re : [Résolu] Script - Options courtes et Arguments

Tawal a écrit :

Si je comprends bien ton code, on pourrait gérer ce genre de situation :

script -r    Doss1    Doss2    Doss3    -r     Doss4    Doss5
#    option  valeur    arg1    arg2   option   valeur    arg3

là, où getopts arrêterait sa recherche d'option au plus tard sur Doss2. Et la prochaine occurrence de "-r" serait interprétée comme un argument positionnel par getopts.

Pour le coup getopt te gère ça tranquille, en te reformatant l'entrée de cette manière à priori :

script -r Doss1 -r Doss4 -- Doss2 Doss3 Doss5

qui peut se parser ensuite assez naturellement par quelque chose du type

while [ "$1" != '--' ]; do
  …
  shift
done

ou autre… mais je ne veux pas à tout prix faire de la pub pour getopt ! big_smile (pour lequel j'avoue cependant avoir un faible)

Hors ligne

#20 Le 09/03/2021, à 20:22

Tawal

Re : [Résolu] Script - Options courtes et Arguments

Je vais essayer d'exprimer pourquoi je préfère les buit-in et comment je vois l'utilisation des commandes externes.

Plus on utilise les primitives, plus on est indépendant du système/environnement.
De plus, l’exécution d'une commande externe se fait dans un sous-shell, d'où son impossibilité d'affecter les variables du shell appelant.
En fait, je vois une commande externe comme un script externe donc je cherche une solution "built-in".

Après, les commandes externe ne sont pas inutiles, loin de ça.
Mais autant les utiliser pour subvenir aux incapacités de bash.

C'est mon point de vue simplifié et non-immuable avec ma compréhension actuelle ...

Au plaisir.


Le savoir n'a d’intérêt que si on le transmet.
Useless Use of Cat Award
Filenames and Pathnames in Shell: How to do it Correctly
À chaque problème sa solution, à chaque solution son moyen, si pas de moyen, toujours le problème !

Hors ligne