1

I want to create a bash function that will accept variable number of parameters. There must be at least one parameter. Then I call another program and need to insert fixed values between the first parameter accepted and the rest of parameters.

I do it based on this answer

tt() {
  name="$1"
  params="${@:2}"
  someapp ${name} 1234 /some/path "${params}"
}

But it doesn't work as intended as if I call it

tt John has fun

the resulting call will be

someapp John 1234 /some/path 'has fun' 

note quotes, while I need the result to be

someapp John 1234 /some/path has fun 

with two last args not in common quotes.

Kusalananda
  • 333,661

1 Answers1

2

Pick out the first argument, shift, then call your other command with the saved 1st argument, and the remaining ones:

tt () {
   name=$1
   shift

someapp "$name" 1234 /some/path "$@" }

Alternatively, with a named array like what you attempted:

tt () {
    name=$1
    params=( "${@:2}" )
someapp "$name" 1234 /some/path "${params[@]}"

}

The main issue with your own code is that you are not creating or using the params variable as an array. Doing that correctly would look like params=( "${@:2}" ) followed by using at as "${params[@]}", including the double quotes and the [@] bit.

Array assignments always look like name=( ... ), so what you get with params="${@:2}" is not an array but a single string consisting of the 2rd element onward from "$@", concatenated with spaces as delimiters.

Without the double quotes in "${params[@]}", the shell would split each element of the array on spaces, tabs, and newlines (the characters in $IFS by default), and then apply filename globbing on each generated word. Without [@], you only get the first element of the array.


A minimalistic rewrite:

tt () { someapp "$1" 1234 /some/path "${@:2}"; }
Kusalananda
  • 333,661
  • I'm using the first snippet with $@ (note: no quotes) as I read that "$@" and $@ produce different results in case arguments contain spaces. Is my understanding and use correct? – Ivan Onyshchenko Jan 12 '23 at 15:39
  • @IvanOnyshchenko $@ should always be quoted! Without quotes, the shell would split the strings in the argument list up into more strings on spaces, tabs, and newlines and perform filename globbing on those new strings. This essentially stops you from passing arguments containing spaces (or at least doing it correctly, preserving the spaces). Please also read the answers to What is the difference between $* and $@? – Kusalananda Jan 12 '23 at 15:42