0

I have a main script (main.bash)

#!/bin/bash
var=10                 #Variable to pass to the nested script
./nested.bash $var     #Pass 'var' to the nested script, which outputs the 'list' array
echo $list             #echo the output of the nested script

The nested script (nested.bash) is:

#!/bin/bash
if [ $1 == 10 ] ; then    
    list=(10-10 20-01 30-03 40-01 50-05)
fi
export list

I used export, but it is not working. How can 'nested.bash' pass list array to 'main.bash'? More generally, how can this be done?

1
  • You can only export variables to child processes, not the parent process. Commented Sep 3, 2020 at 23:47

2 Answers 2

2

The simplest solution is to source the script with .. This runs it in the current shell process instead of in a child process, which means the outer script can see the changes made by the nested script.

main

#!/bin/bash
var=10
. ./nested.bash "$var"
echo "${list[@]}"

nested.bash

if [ "$1" == 10 ]; then    
    list=(10 20 30 40 50)
fi

Notes:

  • Executables should generally not have an extension. The caller doesn't need to know if the script is written in bash or python or is a compiled C program. Prefer main to main.bash.

  • Sourced scripts, on the other hand, should have an extension since they need to be executed in a particular interpreter. Name the inner script nested.bash.

  • Always quote variable expansions.

  • Array expansion is "${list[@]}". If you write $list you'll only get the first element.

  • You don't have to pass "$var" in and reference it as "$1" in the nested script. You can reference "$var" directly if you like.

Sign up to request clarification or add additional context in comments.

Comments

1

You can't export variables to a parent process. export is only used to pass variables to child processes. It's also not possible to export arrays.

The way to send data back to the parent process is through standard output, using command substitution.

main.bash:

#!/bin/bash
var=10                 
list=($(./nested.bash "$var"))
echo "${list[@]}"

nested.bash:

#!/bin/bash
if [ $1 == 10 ] ; then    
    list=(10 20 30 40 50)
fi
echo "${list[@]}"

1 Comment

It is a risky method to pass arrays like this. Bash has better ways to pass lists as null or ASCII FS \37 delimited entries to be read-back with mapfile -d '' list < <(nested.bash) or mapfile -d $'\37' list < <(nested.bash having nested.bash do printf %s\\0 "${list[@]}" or printf %s\\37 "${list[@]}". The ASCII FS method can also work with older bash having only read -a and no mapfile, as read -a cannot read null delimited entries all at once, since it uses the IFS variable for record separation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.