#1 Le 08/03/2021, à 16: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 )
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"
Au plaisir.
Dernière modification par Tawal (Le 11/03/2021, à 17: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, à 17: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, à 17:56)
Hors ligne
#3 Le 08/03/2021, à 17:40
- Tawal
Re : [Résolu] Script - Options courtes et Arguments
Merci de ta réponse.
# Plus nécessaire ? Sauf si j'ai mal interprété le sens de l'option -h
Très bonne interprétation
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 ?
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, à 17: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.
Dernière modification par beuguissime (Le 08/03/2021, à 18:05)
Hors ligne
#5 Le 08/03/2021, à 18: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, à 18:59)
Hors ligne
#6 Le 08/03/2021, à 18:58
- kamaris
Re : [Résolu] Script - Options courtes et Arguments
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, à 18:58)
Hors ligne
#7 Le 08/03/2021, à 19: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, à 20:08
- Tawal
Re : [Résolu] Script - Options courtes et Arguments
Super
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
Dernière modification par Tawal (Le 08/03/2021, à 20: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, à 22: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 08/03/2021, à 23: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 08/03/2021, à 23: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 08/03/2021, à 23:36
- Tawal
Re : [Résolu] Script - Options courtes et Arguments
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 08/03/2021, à 23: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, à 00: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, à 00: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, à 08: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, à 08: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, à 09: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, à 10: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, à 10: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, à 12:56
- Hizoka
Re : [Résolu] Script - Options courtes et Arguments
En toute logique tu peux tout faire dont ce que tu proposes
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#19 Le 09/03/2021, à 18:32
- kamaris
Re : [Résolu] Script - Options courtes et Arguments
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 ! (pour lequel j'avoue cependant avoir un faible)
Hors ligne
#20 Le 09/03/2021, à 19: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