Pass multi-word arguments to a bash function

haelix picture haelix · Apr 8, 2012 · Viewed 17.5k times · Source

Inside a bash script function, I need to work with the command-line arguments of the script, and also with another list of arguments. So I'm trying to pass two argument lists to a function, the problem is that multi-word arguments get split.

function params()
{
    for PARAM in $1; do
        echo "$PARAM"
    done

    echo .

    for ITEM in $2; do
        echo "$ITEM"
    done
}

PARAMS="$@"
ITEMS="x y 'z t'"
params "$PARAMS" "$ITEMS"

calling the script gives me

myscript.sh a b 'c d'
a
b
c
d
.
x
y
'z
t'

Since there are two lists they must be passed as a whole to the function, the question is, how to iterate the elements while respecting multi-word items enclosed in single quotes 'c d' and 'z t'?

The workaround that I have (see below) makes use of BASH_ARGV so I need to pass just a single list to the function. However I would like to get a better understanding of what's going on and what's needed to make the above work.

function params()
{
    for PARAM in "${BASH_ARGV[@]}"; do
        echo "$PARAM"
    done

    echo .

    for ITEM in "$@"; do
        echo "$ITEM"
    done
}

params x y 'z t'

calling the script gives me

myscript.sh a b 'c d'
c d
b
a
.
x
y
z t

... Which is how I need it (except that first list is reversed, but that would be tolerable I guess)

Answer

Peter.O picture Peter.O · Apr 8, 2012
function params()
{
   arg=("$@")

   for ((i=1;i<=$1;i++)) ;do
       echo "${arg[i]}"
   done

   echo .

   for ((;i<=$#-$1+2;i++)) ;do
       echo "${arg[i]}"
   done
}

items=(w x 'z t')
params $# "$@" "${items[@]}"

Assuming you call your script with args a b 'c d', the output is:

a
b
c d
.
x
y
z t