Estás sufriendo de ilusiones; utilizando getopts
no requiere argumentos obligatorios con el prefijo de una letra de bandera. Traté de encontrar un ejemplo adecuado de mi corpus de scripts; esta es una aproximación semi-decente. Se llama rcsunco
y se utiliza para cancelar una salida de RCS. No lo he modificado desde hace un tiempo, ya veo; Lo uso con bastante frecuencia (porque aún no he migrado completamente de RCS).
#!/bin/sh
#
# "@(#)$Id: rcsunco.sh,v 2.1 2002/08/03 07:41:00 jleffler Exp $"
#
# Cancel RCS checkout
# -V print version number
# -n do not remove or rename checked out file (like SCCS unget) (default)
# -r remove checked out file (default)
# -k keep checked out file as $file.keep
# -g checkout (unlocked) file after clean-up
# -q quiet checkout
: ${RCS:=rcs}
: ${CO:=co}
remove=yes
keep=no
get=no
quiet=
while getopts gknqrV opt
do
case $opt in
V) echo "`basename $0 .sh`: RCSUNCO Version $Revision: 2.1 $ ($Date: 2002/08/03 07:41:00 $)" |
rcsmunger
exit 0;;
g) get=yes;;
k) keep=yes;;
n) remove=no;;
q) quiet=-q;;
r) remove=yes;;
*) echo "Usage: `basename $0 .sh` [-{n|g}][-{r|k}] file [...]" 1>&2
exit 1;;
esac
done
shift $(($OPTIND-1))
for file in $*
do
rfile=$(rfile $file)
xfile=$(xfile $rfile)
if $RCS -u $rfile
then
if [ $keep = yes ]
then
if [ -f $xfile ]
then
mv $xfile $xfile.keep
echo "$xfile saved in $xfile.keep"
fi
elif [ $remove = yes ]
then rm -f $xfile
fi
if [ $get = yes ] && [ $remove = yes -o $keep = yes ]
then $CO $quiet $rfile
fi
fi
done
Es solo una aproximación semi-decente; el script silenciosamente no hace nada si no proporciona ningún nombre de archivo después de los argumentos opcionales. Sin embargo, si lo necesita, puede verificar que los argumentos obligatorios estén presentes después del 'cambio'. Otro script mío tiene argumentos obligatorios. Contiene:
...
shift $(($OPTIND - 1))
case $# in
2) case $1 in
install) MODE=Installation;;
uninstall) MODE=Uninstallation;;
*) usage;;
esac;;
*) usage;;
esac
Por lo tanto, esta orden (jlss
) puede tomar argumentos opcionales, tales como -d $HOME
, pero requiere ya sea install
o uninstall
seguido por el nombre de algo de instalar. El modo básico de uso es:
jlss install program
Pero el modo opcional es:
jlss -d $HOME -u me -g mine -x -p install program
I, no mostró todos jlss
ya que tiene cerca de 12 opciones - no es tan compacto como rcsunco
.
Si se tratara de argumentos obligatorios antes de argumentos de opciones, entonces usted tendría que hacer un poco más de trabajo:
- Se quedaría con los argumentos obligatorios, ellos desplazando fuera de la camino.
- Luego procesa los argumentos opcionales con los indicadores.
- Finalmente, si corresponde, maneja los argumentos adicionales de 'nombre de archivo'.
Si se trata de argumentos obligatorios intercalados con argumentos de opción (tanto antes como después de los obligatorios), entonces todavía tiene más trabajo por hacer. Esto es utilizado por muchos sistemas VCS; CVS y GIT tanto tienen la facilidad:
git -global option command [-sub option] [...]
Aquí, se corre un getopts
bucle para obtener las opciones globales; recoger los argumentos obligatorios; y ejecute un segundo bucle getopts
para obtener las subopciones (y quizás ejecute un bucle final sobre los argumentos de 'nombre de archivo').
¿No es divertido la vida?
Parece que hace exactamente lo que yo quiero. Una pregunta con esto, sin embargo: si quiero permitir un indicador que toma un argumento (por ejemplo, -l archivo.txt), ¿cuál sería la sintaxis? Gracias de nuevo. –
Consulte la página getopt man para eso. Brevemente: agregue dos puntos a la opción (por ejemplo, '" -rv: x "', que requiere v para tomar un argumento). También se admiten opciones largas, que es una de las formas en que triunfa sobre los getopts integrados. Tenga en cuenta que tendrá que manejar el argumento adicional no opcional usted mismo. – Sorpigal
Muchas gracias. Una excelente respuesta. –