55

Hi i have the following:

bash_script parm1 a b c d ..n

I want to iterate and print all the values in the command line starting from a, not from parm1

Alberto Zaccagni
  • 29,658
  • 11
  • 72
  • 103
piet
  • 745
  • 3
  • 8
  • 9
  • 1
    possible duplicate of [Remove first element from $@ in bash](http://stackoverflow.com/questions/2701400/remove-first-element-from-in-bash) – user May 01 '14 at 15:29

5 Answers5

147

You can "slice" arrays in bash; instead of using shift, you might use

for i in "${@:2}"
do
    echo "$i"
done

$@ is an array of all the command line arguments, ${@:2} is the same array less the first element. The double-quotes ensure correct whitespace handling.

James Newton
  • 6,203
  • 7
  • 44
  • 97
Ismail Badawi
  • 33,928
  • 7
  • 80
  • 95
  • 3
    Be careful, as slicing may cause problems with whitespace in e.g. globbed paths. The file `folder/my file` will be split to `folder/my` and `file` if invoked as `./script.sh folder/*`. The accepted answer using `shift` and `$1` works as intended in this case. – jkgeyti Jan 08 '15 at 09:50
  • 7
    @jkgeyti This isn't a problem with globbed paths, just a problem with whitespace handling. Properly quoting like `for i in "${@:2}"; do echo "$i"; done` fixes that issue. – Erik Feb 05 '16 at 19:25
  • Could someone edit the quotes into the answer? I'd have almost missed the comment that fixes the whitespace issue. – wrtlprnft Oct 25 '17 at 12:00
29

This should do it:

#ignore first parm1
shift

# iterate
while test ${#} -gt 0
do
  echo $1
  shift
done
Sebastian
  • 5,783
  • 5
  • 32
  • 46
Scharron
  • 16,483
  • 6
  • 41
  • 63
9

This method will keep the first param, in case you want to use it later

#!/bin/bash

for ((i=2;i<=$#;i++))
do
  echo ${!i}
done

or

for i in ${*:2} #or use $@
do
  echo $i
done
ghostdog74
  • 307,646
  • 55
  • 250
  • 337
8

Another flavor, a bit shorter that keeps the arguments list

shift
for i in "$@"
do
  echo $i
done
Déjà vu
  • 27,162
  • 5
  • 70
  • 97
  • (You might also change `echo $i` to `echo "$i"` -- that way `./yourscript '*'` actually prints `*`, not a list of files; it also means that `./yourscript $'argument\twith\ttabs'` actually prints tabs, instead of having them changed to spaces). – Charles Duffy Sep 01 '17 at 11:53
7

You can use an implicit iteration for the positional parameters:

shift
for arg
do
    something_with $arg
done

As you can see, you don't have to include "$@" in the for statement.

Dennis Williamson
  • 324,833
  • 88
  • 366
  • 429