Process all arguments except the first one (in a bash script)

I have a simple script where the first argument is reserved for the filename, and all other optional arguments should be passed to other parts of the script.

Using Google I found this wiki, but it provided a literal example:

echo "${@: -1}"

I can't get anything else to work, like:

echo "${@:2}"

or

echo "${@:2,1}"

I get "Bad substitution" from the terminal.

What is the problem, and how can I process all but the first argument passed to a bash script?


Solution 1:

Use this:

echo "${@:2}"

The following syntax:

echo "${*:2}"

would work as well, but is not recommended, because as @Gordon already explained, that using *, it runs all of the arguments together as a single argument with spaces, while @ preserves the breaks between them (even if some of the arguments themselves contain spaces). It doesn't make the difference with echo, but it matters for many other commands.

Solution 2:

If you want a solution that also works in /bin/sh try

first_arg="$1"
shift
echo First argument: "$first_arg"
echo Remaining arguments: "$@"

shift [n] shifts the positional parameters n times. A shift sets the value of $1 to the value of $2, the value of $2 to the value of $3, and so on, decreasing the value of $# by one.

Solution 3:

Working in bash 4 or higher version:

#!/bin/bash
echo "$0";         #"bash"
bash --version;    #"GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu)"

In function:

echo $@;              #"p1" "p2" "p3" "p4" "p5"
echo ${@: 0};  #"bash" "p1" "p2" "p3" "p4" "p5"
echo ${@: 1};         #"p1" "p2" "p3" "p4" "p5"
echo ${@: 2};              #"p2" "p3" "p4" "p5"
echo ${@: 2:1};            #"p2"
echo ${@: 2:2};            #"p2" "p3"
echo ${@: -2};                       #"p4" "p5"
echo ${@: -2:1};                     #"p4"

Notice the space between ':' and '-', otherwise it means different:

${var:-word} If var is null or unset,
word is substituted for var. The value of var does not change.

${var:+word} If var is set,
word is substituted for var. The value of var does not change.

Which is described in:Unix / Linux - Shell Substitution

Solution 4:

http://wiki.bash-hackers.org/scripting/posparams

It explains the use of shift (if you want to discard the first N parameters) and then implementing Mass Usage