getoptet getoptssont des bêtes différentes, et les gens semblent avoir un peu de malentendu sur ce qu'ils font. getoptsest une commande intégrée permettant bashde traiter les options de ligne de commande dans une boucle et d'affecter tour à tour chaque option et valeur trouvées aux variables intégrées, afin que vous puissiez les traiter davantage. getopt, cependant, est un programme utilitaire externe, et il ne traite pas réellement vos options pour vous comme le font par exemple bash getopts, le Getoptmodule Perl ou Python optparse/ argparsemodules. Tout ce getoptqui est fait est de canoniser les options qui sont passées - c'est-à-dire les convertir en une forme plus standard, afin qu'il soit plus facile pour un script shell de les traiter. Par exemple, une application de getoptpourrait convertir les éléments suivants:
myscript -ab infile.txt -ooutfile.txt
en cela:
myscript -a -b -o outfile.txt infile.txt
Vous devez effectuer vous-même le traitement. Vous ne devez pas utiliser getoptdu tout si vous faites diverses restrictions sur la façon dont vous pouvez spécifier les options:
- ne mettez qu'une seule option par argument;
- toutes les options passent avant tous les paramètres positionnels (c'est-à-dire les arguments sans option);
- pour les options avec des valeurs (par exemple
-oci-dessus), la valeur doit aller comme un argument séparé (après un espace).
Pourquoi utiliser getoptau lieu de getopts? La raison fondamentale est que seul GNU getoptvous permet de prendre en charge les options de ligne de commande portant un nom long. 1 (GNU getoptest la valeur par défaut sous Linux. Mac OS X et FreeBSD sont livrés avec une version basique et pas très utilegetopt , mais la version GNU peut être installée; voir ci-dessous.)
Par exemple, voici un exemple d'utilisation de GNU getopt, à partir d'un de mes scripts appelé javawrap:
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
Cela vous permet de spécifier des options similaires --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"ou similaires. L'appel à a getoptpour effet de canoniser les options pour --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"que vous puissiez les traiter plus facilement. La citation autour "$1"et "$2"est importante car elle garantit que les arguments avec des espaces sont traités correctement.
Si vous supprimez les 9 premières lignes (tout en haut de la eval setligne), le code fonctionnera toujours ! Cependant, votre code sera beaucoup plus pointilleux dans les types d'options qu'il accepte: En particulier, vous devrez spécifier toutes les options sous la forme "canonique" décrite ci-dessus. getoptCependant, avec l'utilisation de , vous pouvez regrouper des options à une seule lettre, utiliser des formes non ambiguës plus courtes d'options longues, utiliser le style --file foo.txtou --file=foo.txt, utiliser le style -m 4096ou -m4096, mélanger les options et les non-options dans n'importe quel ordre, etc. getoptgénère également un message d'erreur si des options non reconnues ou ambiguës sont trouvées.
REMARQUE : Il existe en fait deux versions totalement différentes de getopt, de base getoptet GNU getopt, avec des fonctionnalités différentes et des conventions d'appel différentes. 2 Basic getoptest assez cassé: non seulement il ne gère pas les options longues, mais il ne peut même pas gérer les espaces incorporés à l'intérieur des arguments ou des arguments vides, alors getoptsqu'il le fait correctement. Le code ci-dessus ne fonctionnera pas en base getopt. GNU getoptest installé par défaut sous Linux, mais sous Mac OS X et FreeBSD, il doit être installé séparément. Sur Mac OS X, installez MacPorts ( http://www.macports.org ), puis sudo port install getoptinstallez GNU getopt(généralement dans /opt/local/bin) et assurez-vous qu'il se /opt/local/bintrouve dans votre chemin de shell avant/usr/bin. Sur FreeBSD, installez misc/getopt.
Un guide rapide pour modifier l'exemple de code pour votre propre programme: Sur les premières lignes, tout est "passe-partout" qui doit rester le même, sauf la ligne qui appelle getopt. Vous devez modifier le nom du programme après -n, spécifier les options courtes après -oet les options longues après --long. Mettez deux points après les options qui prennent une valeur.
Enfin, si vous voyez du code qui vient de setremplacer eval set, il a été écrit pour BSD getopt. Vous devriez le changer pour utiliser le eval setstyle, qui fonctionne bien avec les deux versions de getopt, tandis que le clair setne fonctionne pas correctement avec GNU getopt.
1 En fait, getoptsin ksh93prend en charge les options nommées depuis longtemps, mais ce shell n'est pas utilisé aussi souvent que bash. Dans zsh, utilisez zparseoptspour obtenir cette fonctionnalité.
2 Techniquement, «GNU getopt» est un terme impropre; cette version a été écrite pour Linux plutôt que pour le projet GNU. Cependant, il suit toutes les conventions GNU, et le terme "GNU getopt" est couramment utilisé (par exemple sur FreeBSD).