I came up with this solution for foo.sh :
#!/bin/bash
echo "executing foo.sh:"
function arg_remove ()
{
local array=("${@:3}")
for ((i=0; i<"${#array[@]}"; ++i)); do
case ${array[i]} in
"$2") unset array[i]; unset array[i+1]; break ;;
esac
done
# clean up unset array indexes
for i in "${!array[@]}"; do
new_array+=( "${array[i]}" )
done
array=("${new_array[@]}")
unset new_array
# assign array outside function scope
local -g "$1=( )"
eval ${1}='("${array[@]}")'
}
echo "arguments income :" "$@"
arg_remove ARG_PASS '--argname' "$@"
echo "arguments passed :" "${ARG_PASS[@]}"
./bar.sh "${ARG_PASS[@]}"
The second output test script will only print all passed arguments grouped line by line bar.sh :
#!/bin/bash
echo "executing bar.sh:"
while [[ $# -gt 0 ]]
do
key="$1"
if [[ "$key" == --* ]]; then
shift
echo $key $1
else
echo $key
fi
shift
done
Now calling the first script results in:
$ ./foo.sh -v --first val1 --argname 'value with spaces' --last val3
executing foo.sh:
arguments income : -v --first val1 --argname value with spaces --last val3
arguments passed : -v --first val1 --last val3
executing bar.sh:
-v
--first val1
--last val3
You can also simplify the code and remove the separation of function arg_remove and clean up so you get a minimalistic version of foo_mini.sh without the need for eval:
#!/bin/bash
args=("${@}")
filter="--argname"
for ((i=0; i<"${#args[@]}"; ++i)); do
case ${args[i]} in
"$filter") unset args[i]; unset args[i+1]; break ;;
esac
done
./bar.sh "${args[@]}"