265

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?

3 Answers 3

362

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.

Sign up to request clarification or add additional context in comments.

9 Comments

actually "$@" is safer than $*
$@ 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: tldp.org/LDP/abs/html/internalvariables.html#APPREF
Pay attention to use quotes! Read more on why it is important them around here: stackoverflow.com/a/4824637/4575793
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 "$@"
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.
|
68

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
    

Comments

55

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

5 Comments

@TamásZahola care to explain?
If you forward the arguments as $1 without quoting them as "$1", then the shell will perform word splitting, so e.g. foo bar will be forwarded as foo and bar separately.
Read more on why it is important to have the double " around here: stackoverflow.com/a/4824637/4575793
My brain jumbled up a couple of letters in "shifttest" and I consequently read it as something else.
Doesn't this only answer half the question? How do you forward the remaining parameters? Rhetorical question: the accepted answer explains you use forward-to-me.sh "$@"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.