Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

bash

shell

I would like to define a simple abbreviation of a call to gs (ghostscript) via a shell script. The first argument(s) give all the files that should be merged, the last one gives the name of the output file. Obviously, the following does not work (it's just for showing the goal):

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

How can this be done?

One would typically call this script via myscript infile1.pdf infile2.pdf ... outfile.pdf or myscript *.pdf outfile.pdf.

like image 424
Marius Hofert Avatar asked Apr 24 '12 23:04

Marius Hofert


People also ask

How do you pass a number argument in shell script?

Inside the script, we can use the $ symbol followed by the integer to access the arguments passed. For example, $1 , $2 , and so on. The $0 will contain the script name.

How do I pass multiple arguments to a shell script?

To pass multiple arguments to a shell script you simply add them to the command line: # somescript arg1 arg2 arg3 arg4 arg5 … To pass multiple arguments to a shell script you simply add them to the command line: # somescript arg1 arg2 arg3 arg4 arg5 …

How many arguments can be passed to bash script?

NUM} ) in the 2^32 range, so there is a hard limit somewhere (might vary on your machine), but Bash is so slow once you get above 2^20 arguments, that you will hit a performance limit well before you hit a hard limit.

What is $@ and $* in shell script?

"$@" Stores all the arguments that were entered on the command line, individually quoted ("$1" "$2" ...). So basically, $# is a number of arguments given when your script was executed. $* is a string containing all arguments. For example, $1 is the first argument and so on.


2 Answers

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.

like image 57
larsks Avatar answered Sep 21 '22 07:09

larsks


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.

like image 23
Idelic Avatar answered Sep 22 '22 07:09

Idelic