Importing variables in one shell script from another without executing the referred shell script

26,143

Solution 1

There are three options I use when I have a bash script that I want to behave differently when it is sourced vs. when it is executed (or in other words have data items in a script that I want access to without executing any code at that time). The comments touched on them to an extent.

Option One

Determine when being sourced and end 'sourcing' at appropriate time

Separate script into two sections, exit from script when sourced before getting to lower second

Create an upper section of script with definitions (functions / variable assignments / etc), but no direct code execution.

Just before the executable code section starts, place logic that will exit the script if it detects it is being sourced. The following code segment will do this:


file1.sh

#!/usr/bin/env bash
export var1="/data/share"
export var2='password'    
# --- End Definitions Section ---    
# check if we are being sourced by another script or shell
[[ "${#BASH_SOURCE[@]}" -gt "1" ]] && { return 0; }
# --- Begin Code Execution Section ---
echo "Hello"
echo $var1
echo $var2 


file2.sh

#!/usr/bin/env bash 
source file1.sh
echo "$var1"
echo "$var2"


Output of running ./file2.sh

$ ./file2.sh 
/data/share
password

Option Two

This one is usually only used in complex situations, and for this particular example it's overkill. I create a function in the file that I want to source, and in that function determine what should be available to the caller. In this case it's the two exported variables. Normally I use this mode when I have associative arrays, which are otherwise nearly impossible to hand around. Also, the tmp file should be deleted by the caller; but I didn't in this case:


file1.sh

#!/usr/bin/env bash 
export var1="/data/share"
export var2='password'
exportCfg() {
  tmpF=$(mktemp)
  declare -p var1 var2 > "$tmpF"
  echo "$tmpF"
}
if [ "$1" == "export" ]; then
  exportCfg;
  exit 0;
fi

echo "Hello"
echo $var1
echo $var2


file2.sh

#!/usr/bin/env bash 
source $(./file1.sh export)


echo "$var1"
echo "$var2"

The output from executing file2.sh is the same as above

Option 3

The final common way I handle this is simply with a library file that only holds definitions, and has no code that will execute when sourced or directly run. This is simply a matter of dividing up your code. I have a group of bash 'libs' that contain frequently used functions, and on a per project basis usually setup a small sourceable library for storing configuration data (constants). If that data includes populated arrays, then I will also use a version of Option 2.

Solution 2

If your variables are all exported in the same way (export foo=bar), then you can source all of them easily using bash process substitution feature:

source <(grep '^export .*=' file1.sh)

Man page extract:

Process Substitution Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of <(list) or >(list). The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form is used, the file passed as an argument should be read to obtain the output of list.

Share:
26,143

Related videos on Youtube

Mathew
Author by

Mathew

Updated on September 18, 2022

Comments

  • Mathew
    Mathew over 1 year

    I have 2 shell scripts, file1.sh and file2.sh

    file1.sh

    #!/usr/bin/env bash 
    export var1="/data/share"
    export var2='password'
    echo "Hello"
    

    file2.sh

    #!/usr/bin/env bash 
    source file1.sh
    echo $var1
    echo $var2
    

    When i execute file2.sh, I get the following output

    Hello
    /data/share
    password
    

    But my expected output is

    /data/share
    password
    

    file1.sh is getting executed when referred in file2.sh. How do i import the variables alone in file2.sh without executing file1.sh?

    • Michael Vehrs
      Michael Vehrs almost 8 years
      You can't do that. source means execute. The most obvious solution is to put the variable definitions in a config file and source it in both scripts.
    • makgun
      makgun almost 8 years
      Can echo line with this [[ $1 == "SourceIt" ]] & echo "Hello" after that you can get var from script. Use this like this /path/of/file.sh SourceIt
    • Cyrus
      Cyrus almost 8 years
      7 questions and 0 Accepts. Please take a look at: What should I do when someone answers my question?