15

How do I pass an array as a variable from a first bash shell script to a second script.

first.sh
#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
sh second.sh "$AR" # foo
sh second.sh "${AR[@]}" # foo
second.sh
#!/bin/bash
ARR=$1
echo ${ARR[@]}

In both cases, the result is foo. But the result I want is foo bar baz bat.

What am I doing wrong and how do I fix it?

0

3 Answers 3

13

AFAIK, you can't. You have to serialize it and deserialize it, e.g. via the argument array:

first

#!/bin/bash
ar=('foo' 'bar' 'baz' 'bat')
second "${ar[@]}" #this is equivalent to: second foo bar baz bat

second

#!/bin/bash
arr=( "$@" )
printf ' ->%s\n' "${arr[@]}"
<<PRINTS
   -> foo
   -> bar
   -> baz
   -> bat
PRINTS

A little bit of advice:

  • reserve all caps for exported variables
  • unless you have a very good specific reason for not doing so "${someArray[@]}" should always be double quoted; this formula behaves exactly like 'array item 0' 'array item 1' 'aray item 2' 'etc.' (assuming someArray=( 'array item 0' 'aray item 1' 'aray item 2' 'etc.' ) )
1
  • line 1: unexpected EOF while looking for matching `)' ¯\_(ツ)_/¯ Mar 31, 2023 at 18:22
5

The AR array is passed via the first argument to second.sh.

first.sh

#!/bin/bash
AR=('foo' 'bar' 'a space' 'bat')
printf "AR array contains %d elements: " ${#AR[@]}
printf "%s " "${AR[@]}"
printf "\n"
./second.sh "$AR"
./second.sh "$(printf "(" ; printf "'%s' " "${AR[@]}" ; printf ")")"

Note that sh is not used anymore to run the second.sh script.

These chained printf are used to forge a single parameter that will be safe if some array elements contain space chars.

second.sh

#!/bin/bash
declare -a ARR=$1
printf "ARR array contains %d elements: " ${#ARR[@]}
printf "%s " "${ARR[@]}"
printf "\n"

----

For a solution where the AR array is passed using any number of arguments to the second.sh script.

first.sh

#!/bin/bash
AR=('foo' 'bar' 'a space' 'bat')
printf "AR array contains %d elements: " ${#AR[@]}
printf "%s " "${AR[@]}"
printf "\n"
./second.sh "$AR"
./second.sh "${AR[@]}"

second.sh

#!/bin/bash
ARR=( "$@" )
printf "ARR array contains %d elements: " ${#ARR[@]}
printf "%s " "${ARR[@]}"
printf "\n"

----

The test:

$ chmod +x *sh
$ ./first.sh
AR array contains 4 elements: foo bar a space bat
ARR array contains 1 elements: foo
ARR array contains 4 elements: foo bar a space bat
0

first

#!/bin/bash
ar=('foo' 'bar' 'baz' 'bat')
./second "${ar[@]}"

second

#!/bin/bash
read -a arr1 <<< "${BASH_ARGV[@]}"
echo "${arr1[@]}"

This should have been enough, but the array order is reversed so I added:

for (( i=${#arr1[@]}-1,j=0 ; i>=0 ; i--,j++ ))
do
    arr2[j]="${arr1[i]}"
done
echo "${arr2[@]}"

read -a reads input into array arr1, but for some reason I can't figure out, the array is reversed, so I reverse it back into arr2.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .