Comment définir un script shell avec un nombre variable d'arguments?

Je voudrais définir une abréviation simple d'un appel à gs (ghostscript) via un script shell. Le premier argument(s) donner à tous les fichiers qui doivent être fusionnés, le dernier donne le nom du fichier de sortie. Évidemment, ce qui suit ne fonctionne pas (c'est juste pour montrer le but):

#!/bin/sh
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$last $1 $2 ...

Comment cela peut-il être fait?

On appelle généralement ce script via myscript infile1.pdf infile2.pdf ... outfile.pdf ou myscript *.pdf outfile.pdf.

24
demandé sur Marius Hofert 2012-04-25 03:12:14

3 réponses

Les variables bash $@ et $* étendre dans la liste des arguments de ligne de commande. Généralement, vous voudrez utiliser "$@" (c'est-à-dire $@ entouré de guillemets doubles). Cela fera la bonne chose si quelqu'un transmet à votre script un argument contenant des espaces.

Donc, si vous aviez ceci dans votre script:

outputfile=$1
shift
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$outputfile "$@"

Et vous avez appelé votre script comme ceci:

myscript out.pdf foo.ps bar.ps "another file.ps"

Cela s'étendrait à:

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=out.pdf foo.ps bar.ps "another file.ps"

Lisez la section "Paramètres Spéciaux" du manuel bash pour plus d'informations.

35
répondu larsks 2017-10-23 15:15:48

Pour passer le fichier de sortie comme dernier argument, utilisez un tableau:

ARGS=("$@")
# Get the last argument
outputfile=${ARGS[-1]}
# Drop it from the array
unset ARGS[${#ARGS[@]}-1]

exec gs ... -sOUTPUTFILE=$outputfile "${ARGS[@]}"

Avant la version 4, bash n'autorisait pas les indices négatifs dans les tableaux (et produisait l'erreur signalée par Marius dans les commentaires), donc si vous utilisez 3.x vous devez utiliser le beaucoup plus laid

outputfile=${ARGS[${#ARGS[@]}-1]}

Cela fonctionne pour bash 4.x ainsi.

18
répondu Idelic 2012-04-25 14:48:01

Pour accéder au dernier argument, en plus de la réponse D'Idelic ci-dessus, vous pouvez également faire:

echo "${@: $#}"

Cela lit tous les arguments et les imprime à partir du dernier. De cette façon, vous pouvez également accéder aux N derniers arguments, par exemple pour les trois derniers arguments:

echo "${@: $#-2}"

$ ./script "what    does" "this  script" "do" "?"
this  script do ?
7
répondu Ran Lottem 2017-02-03 04:01:32