There are several approaches available, each with their own disadvantages.
The Easy Way: Run The Inner Script Inside A Subshell
This means all variables are inherited, including ones (like arrays!) that can't be passed through the environment.
a=(1 2)
b=(3 4 5)
(. inner)
Of course, it also means that shell settings (IFS, set -e, etc) are inherited too, so inner.sh needs to be written robustly to handle whatever setup it may happen to receive; and you can't rewrite it in a different / non-shell language later.
The Unsafe Way: Pass eval-able code (and trust your caller!)
Modify inner.sh to run [[ $setup ]] && eval "$setup", and then invoke it as:
setup=$(declare -p a b) ./inner
Obviously, this is a severe security risk if you don't control the process environment.
The Hard Way: Deserialize into individual elements
Here, we pass each array as its name, its length, and then its original elements.
inner needs to be modified to copy items off its command-argument list back into the arrays, as in the following example:
while (( $# )); do # iterating over our argument list:
dest_name=$1; shift # expect the variable name first
dest_size=$1; shift # then its size
declare -g -a "$dest_name=( )" # initialize our received variable as empty
declare -n dest="$dest_name" # bash 4.3: make "dest" point to our target name
while (( dest_size )) && (( $# )); do # and then, for up to "size" arguments...
dest+=( "$1" ); shift # pop an argument off the list onto an array
(( dest_size -= 1 )) # and decrease the count left in "size"
done
unset -n dest # end that redirection created above
done
...and then expand into that format in outer:
./inner a "${#a[@]}" "${a[@]}" b "${#b[@]}" "${b[@]}"
shdoesn't support arrays at all. Maybe you wantedbash inner.sh?.shextensions for bash scripts is great practice: Using a.shextension implies that your code is POSIX sh compliant, which it isn't if it uses arrays; and also means that if you rewrite it to use a different interpreter, you need to rename it and then modify every single caller unless you want the name to be misleading. If a script is meant to be executed rather than sourced, better to use no extension at all, and let its shebang be used to a select an interpreter).a_arr=($a)in inner.sh deserializing that you commented?