How to define a shell script with variable number of arguments?

To pass the output file as the last argument, use an array:

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

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

Before version 4, bash didn't allow negative subscripts in arrays (and produced the error reported by Marius in the comments), so if you're using 3.x you need to use the much uglier

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

This works for bash 4.x as well.


The bash variables $@ and $* expand into the list of command line arguments. Generally, you will want to use "$@" (that is, $@ surrounded by double quotes). This will do the right thing if someone passes your script an argument containing whitespace.

So if you had this in your script:

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

And you called your script like this:

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

This would expand to:

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

Read the "Special Parameters" section of the bash man page for more information.


To access the last argument, in addition to Idelic's answer above, you can also do:

echo "${@: $#}"

This reads all of the arguments and prints them starting from the last one. This way, you can also access the N last arguments, for example for the last three arguments:

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

$ ./script "what    does" "this  script" "do" "?"
this  script do ?

Tags:

Shell

Bash