How to pop the last positional argument of a bash function or script?

You can access the last element with ${argv[-1]} (bash 4.2 or above) and remove it from the array with the unset builtin (bash 4.3 or above):

last=${argv[-1]}
unset 'argv[-1]'

The quotes around argv[-1] are required as [...] is a glob operator, so argv[-1] unquoted could expand to argv- and/or argv1 if those files existed in the current directory (or to nothing or cause an error if they didn't with nullglob/failglob enabled).


How about this:

foo () {
    local last="${!#}"
    local argv=("${@:1:$#-1}")
    echo "last: $last"
    echo "rest: ${argv[@]}"
}

You can simplify a little to make it easier on the eye, but the fundamental method is unchanged (this might be useful if you have a Bash version which doesn't support Quasímodo's offering):

foo () {
    local argv=( "$@" )
    local last="${argv[$# - 1]}"
    argv=( "${argv[@]:0:$# - 1}" )
    echo "last: $last"
    echo "rest: ${argv[@]}"
}

I concede that it's a bit cheeky use $# in this way, but it has the same value as ${#argv[@]} in this specific example and is more concise in code.