Get all but first N arguments to a bash function

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:~/"
}

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.