1

If the command my_command has this output:

VAR1=some_value
VAR2=other_value

is it possible to call my_command from a shell script so that both VAR1 and VAR2 are saved as environment variables?

I tried the following ways, and none of them works:

#!/bin/bash
source my_command
export `my_command`

However if I manually enter

export `my_command`

in a terminal console, then both variables are saved.

Jivan
  • 899

2 Answers2

4

If you have my_command like this:

#!/bin/sh
echo 'VAR1=some_value'
echo 'VAR2=other_value'

running it obviously prints

VAR1=some_value
VAR2=other_value

Now, source my_command will run the script, in the current shell, which will just produce the assignments as output. You would use source if my_command didn't print the assignments, but executed then directly.

export $(my_command) will take the output of the script, and pass it to export, which will put the variables in the current shell environment, but it only works as long as the variables in question don't contain whitespace or glob characters, since the command substitution is unquoted. Putting "$(my_command)" in quotes doesn't really help, because then export sees VAR1=some_value\nVAR2=other_value as one argument, and only VAR1 is set.

Note that having running export $(my_command) or setting variables in any other way within another script will not set those variables in the parent shell. If you want the assignments in your interactive shell, you must run them there, but you could wrap the assigments in a function or source a script that makes the assignments.


One, obvious solution would be to do what ssh-agent does, and have the script output export commands for the variables it sets. Then it would be enough to run eval "$(my_command)".

If we don't want to do that, we can use set -a before the script to have the shell automatically export any variables that are set.

So,

$ set -a
$ eval "$(my_command)"

In Bash, we can use declare -p to check that the variables are exported (-x):

$ declare -p VAR1 VAR2
declare -x VAR1="some_value"
declare -x VAR2="other_value"

Using eval here will allow the script to output quoted strings like VAR1="foo bar", and they will be handled correctly. eval will also run anything else the script my_command outputs, not just assignments, but if you didn't trust my_command, you shouldn't run it at all.

ilkkachu
  • 138,973
2

You can't set variables of the parent shell in a shell script you call from it. Either

  • set the variables as usual in the script but source it: . my_command
  • have the script print the variables to be set to stdout and evaluate the result

    $ cat foo.sh 
    #!/bin/sh
    echo FOO=foo
    echo BAR=bar
    $ ./foo.sh 
    FOO=foo
    BAR=bar
    $ eval $(./foo.sh)
    $ echo $FOO
    foo
    $ echo $BAR
    bar
    
nohillside
  • 3,251
  • Took me an hour to find this answer. This is what you want to do instead of piping to bash or trying other ways of executing stdout. Thanks! – blakev May 04 '20 at 18:31