249

Inside my bash script, I would like to parse zero, one or two parameters (the script can recognize them), then forward the remaining parameters to a command invoked in the script. How can I do that?

Brian
  • 14,610
  • 7
  • 35
  • 43
Łukasz Lew
  • 48,526
  • 41
  • 139
  • 208

3 Answers3

341

Use the shift built-in command to "eat" the arguments. Then call the child process and pass it the "$@" argument to include all remaining arguments. Notice the quotes, they should be kept, since they cause the expansion of the argument list to be properly quoted.

Al.G.
  • 4,327
  • 6
  • 31
  • 56
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 32
    actually "$@" is safer than $* – pixelbeat Oct 08 '09 at 13:10
  • 1
    @pixelbeat: Thanks, good catch. I edited. @Łukasz Lew: see the linked-to page in the manual. :) Basically, it handles quoting better. – unwind Oct 08 '09 at 13:18
  • 27
    `$@` essentially treats each element of the array as a quoted string - they are passed along without opportunity for expansion. It also ensures that each is seen as a separate word. This explanation along with a test script demonstrating the difference is here: http://tldp.org/LDP/abs/html/internalvariables.html#APPREF – Cascabel Oct 08 '09 at 14:43
  • 3
    Pay attention to use quotes! Read more on why it is important them around here: http://stackoverflow.com/a/4824637/4575793 – Cadoiz Jul 13 '19 at 15:59
  • Note: If you are just trying to send all of the parameters to the function, don't use shift. – Jared Beach Dec 20 '20 at 22:04
  • 1
    to clarify a quesiton I had before trying this solution: `"$@"` does not pass the script/command name itself as a parameter, unlike `sys.argv[0]` in C-family language. In other words, you're good to simply call whatever command it was as `cmd_inside_script "$@"` – axolotl Feb 03 '22 at 21:39
  • @JaredBeach yes, I came to the same conclusion, I think the answer could benefit from a short explanation of why you would want to use `shift`, as even after reading the doc, I do not really understand the purpose of that command - but maybe I'm just dumb :) – djfm May 02 '23 at 08:06
  • Too many pending edits to add myself, but this answer would be improved with a simple code snippet example. It's unclear if `shift` requires arguments without looking at the docs or reading other answers with examples. – ben-albrecht Jun 14 '23 at 13:46
60

Bash supports subsetting parameters (see Subsets and substrings), so you can choose which parameters to process/pass like this.

  1. open new file and edit it: vim r.sh:

    echo "params only 2    : ${@:2:1}"
    echo "params 2 and 3   : ${@:2:2}"
    echo "params all from 2: ${@:2:99}"
    echo "params all from 2: ${@:2}"
    
  2. run it:

    $ chmod u+x r.sh
    $ ./r.sh 1 2 3 4 5 6 7 8 9 10
    
  3. the result is:

    params only 2    : 2
    params 2 and 3   : 2 3
    params all from 2: 2 3 4 5 6 7 8 9 10
    params all from 2: 2 3 4 5 6 7 8 9 10
    
Robert Lujo
  • 15,383
  • 5
  • 56
  • 73
49

bash uses the shift command:

e.g. shifttest.sh:

#!/bin/bash
echo $1
shift
echo $1 $2

shifttest.sh 1 2 3 produces

1
2 3
Steve B.
  • 55,454
  • 12
  • 93
  • 132