8

I'm aware of how to get the last argument passed to a function but I'm wondering how to get all the arguments of a function after the first two:

For instance:

function custom_scp(){
    PORT=$1
    USER=$2
    SOURCES=`ALL_OTHER_ARGS`
    scp -P $PORT -r $SOURCES [email protected]:~/
}

So sending three files to the remote home directory would look like

$ custom_scp 8001 me ./env.py ./test.py ./haha.py
2
  • 3
    BTW, see wiki-dev.bash-hackers.org/scripting/obsolete -- function foo() { is mixing POSIX sh and ksh function declaration formats in a way that's compatible with neither POSIX sh nor with legacy ksh. Pick one or the other: foo() { is the POSIX form, function foo { is the ksh form. Commented Feb 13, 2019 at 20:34
  • 3
    BTW, re: use of lowercase names in my answer, that's deliberate. USER, for example, is a reserved variable name. By overwriting it, you're potentially breaking other commands run later in the same session. See pubs.opengroup.org/onlinepubs/9699919799/basedefs/… -- all-caps names are used for variables that modify system behavior, lower-case names are reserved for application use. Setting a shell variable with the same name as an environment variable overwrites the latter, so the namespace rules apply to both sets. Commented Feb 13, 2019 at 20:38

2 Answers 2

12

Just shift off the front ones as you're done with them; what's left will be in "$@".

This has the advantage of being compatible with all POSIX shells (the only extension used in the below is local, and it's a widespread one, even available in dash).

custom_scp() {
  local user port  # avoid polluting namespace outside your function
  port=$1; shift   # assign to a local variable, then pop off the argument list
  user=$1; shift   # repeat
  scp -P "$port" -r "$@" "${user}@myserver.com:~/"
}
7

You can use array slice notation:

custom_scp() {
    local port=$1
    local user=$2
    local sources=("${@:3}")

    scp -P "$port" -r "${sources[@]}" "[email protected]:~/"
}

Quoting from the Bash manual:

${parameter:offset}
${parameter:offset:length}

If parameter is @, the result is length positional parameters beginning at offset.

Not the answer you're looking for? Browse other questions tagged or ask your own question.