0

Without using source to load another Bash config/script file, what is the simplest way to find the value of a Bash variable that is defined in a different (temporary) file?

I have seen similar snippets using cat + while, grep, and even eval but none seem very clean nor can be applied to this scenario it seems...

For example:

update.sh wants to download and verify the value of the variable LATEST in a file /tmp/config before deciding if it should proceed with the update process.

Updated (adding more context):

#!/bin/bash

## current config (includes an existing CONFIG_BUILD variable) ##
source config

## compability for updating config ##
UPDATER_BUILD="FEB2020"

## retrieve latest version of config online ##
wget -O /tmp/config http://mirrors.example.com/config-boilerplate

## ensure retrieved config boilerplate is compatible with current updater ##
CONFIG_LATEST=$(source /tmp/config; echo $CONFIG_BUILD)

if [[ "$CONFIG_LATEST" != "$UPDATER_BUILD" ]]; then
    echo -e "Sorry, this updater is outdated or incompatible."
    exit 1
fi

Updated (again): FML, I was missing the semicolon in the subshell. So the subshell source does actually work fine without any conflicts despite same VAR name already sourced... all that said, if anyone still can comment with non-source solutions, it would be great. I've searched for days and not many discussions on this topic, although I finally found one:

Can I export a variable to the environment from a bash script without sourcing it?

Jesse Nickles
  • 1,435
  • 1
  • 17
  • 25
  • 1
    I'd say that the proper way to do it is using the source command. Otherwise, you should be defining an environment variable. For non-clean solutions, maybe cat grep the variable from the file and evaluating the expression can load the correct value but this will have maaaaany corner cases. – Cristian Ramon-Cortes Feb 21 '20 at 11:30
  • @CristianRamon-Cortes The problem is that it can't be sourced, because a variable of the same name is already being "sourced" from a different config file. Unless there is some way to "temporarily" source it using a sub shell or something? – Jesse Nickles Feb 21 '20 at 11:35
  • redefine the source var to something else. If you have a script that sets var1 again and you can't change this - why not change your script to refer to it as my_var1 instead? – bob dylan Feb 21 '20 at 11:43
  • I don't know how clean is that but you might create a sub-process, source the variable, write it, and capture the output on the main process. Something like: `variable_to_source=$(source /tmp/config; echo $variable_name)` – Cristian Ramon-Cortes Feb 21 '20 at 11:50
  • @CristianRamon-Cortes I have tried that but it does not work for some reason, I'm fairly certain my syntax is correct. It still seems to conflict with the other `source` instance or something. – Jesse Nickles Feb 21 '20 at 12:07
  • @jessuppi what error are you getting? See my answer for a working example of this – bob dylan Feb 21 '20 at 12:10
  • @jessuppi : The script you are posting here looks like a good approach for me. Why don't you like it? You have to run the script somehow to find out the final value of the variables (imagine that a variable is set by `VAR=$RANDOM` or `VAR=$(wc -l < /foo/bar)` .... how can you get the value of such a variable without executing the statements in the same context?) – user1934428 Feb 21 '20 at 12:44

2 Answers2

2

By using source in a subshell)

First script

$ cat test
#!/bin/bash

test=123

(. ./test2; echo $test)
echo $test

Second script

$ cat test2
#!/bin/bash
test=456

Testing

$ ./test 
456
123

Or grep it to a var and remove everything before the last = in case of multiply grep results.

test2=$(grep -o 'test=[0-9a-z]*' test2)
echo "${test2##*=}"

Change script1 to this

$ cat test
#!/bin/bash

test=123

(. ./test2; echo $test)
echo $test

test2=$(grep -o 'test=[0-9a-z]*' test2)
echo "${test2##*=}"

And script2 to this

$ cat test2
#!/bin/bash
test=456; test2=asef
test=5    test3=234
test=

Run test

$ ./test 

123

But there are too many ways to set vars to rely on this method

$ cat test2
#!/bin/bash
test=456; test2=asef
test=5    test3=234
test=
test+=5; ((test--))

$ ./test
4
123
5

Update after question updade) If you want to preserv your vars set them as readonly after soursing:

$ cat test
#!/bin/bash

. test2
declare -r test1 test2
echo $test1 $test2
. test3
echo $test1 $test2

$ cat test2
test1=123
test2=456

$ cat test3
test1=sdf
test2=yuo

$ ./test
123 456
test2: line 1: test1: readonly variable
test2: line 2: test2: readonly variable
123 456

Shell won't allow to source readonly vars

Ivan
  • 6,188
  • 1
  • 16
  • 23
2

You don't need to source it. You can use cat or whatever you want to read into your shell e.g.

#!/bin/bash
echo "myval is empty: $myval "
echo "my_Temp_var" > /tmp/tempvar

myval=$(cat /tmp/tempvar)

echo "myval is no longer empty: $myval "

output:

myval is empty:
myval is no longer empty: my_Temp_var

edit:

For your 'var clash'

just do it like this:

my_var=this_var
my_var_source=$(source /tmp/tempvar; echo $my_var)

echo "my_var is: $my_var"
echo "my_var_source is: $my_var_source"

. /tmp/tempvar

echo "If I don't sub from a subshell then it overrides: $my_var"

output

my_var is: this_var
my_var_source is: Temp_var
If I don't sub from a subshell then it overrides: Temp_var
bob dylan
  • 1,458
  • 1
  • 14
  • 32