30

If I want to inherit environment variables to child processes, i do something like:

export MYVAR=tork

Assume I have a a file site.conf containing assignments of values (that can contain spaces) to variables:

EMAIL="[email protected]"
FULLNAME="Master Yedi"
FOO=bar

Now I would like to process this file whenever I open a new shell (e.g. with some code in ~/.bashrc or ~/.profile), so that any processes started from within that newly opened shell will inherit the assignments via environmental variables.

The obvious solution would be to prefix each line in site.conf with an export and just source the file. However I cannot do this since the file is also read (directly) by some other applications, so the format is fixed.

I tried something like

cat site.conf | while read assignment
do
  export "${assignment}"
done

But this doesn't work, for various reasons (the most important being that export is executed in a subshell, so the variable will never be exported to the children of the calling shell).

Is there a way to programmatically export unknown variables in bash?

1

2 Answers 2

57

Run set -a before sourcing the file. This marks all new and modified variables that follow for export automatically.

set -a
source site.conf
set +a  # Require export again, if desired.

The problem you observed is that the pipe executes the export in a subshell. You can avoid that simply by using input redirection instead of a pipe.

while read assignment; do
  export "$assignment"
done < site.conf

This won't work, however, if (unlikely though it is) you have multiple assignments on one line, such as

EMAIL="[email protected]" FULLNAME="Master Yedi" 
Sign up to request clarification or add additional context in comments.

7 Comments

Your last paragraph is incorrect, export will still work with multiple affectations in a single line.
export does, but the need to quote $assignment breaks it. A line like foo=1 bar=2 results in export "foo=1 bar=2", which sets foo to 1 bar =2. Writing export $assignment wouldn't work if any of the values were quoted: assignment='foo="hello world"' results in an attempt to define an environment variable named world", and assignment='foo="hello"' results in the value of foo being "hello", not hello.
Using an array and export "${assignment[@]}" would work, assuming you could parse a series of assignments into an array; that is beyond read's capabilities in general.
Indeed, I missed the space issue. Leaving the variable unquoted and using eval would be simpler and allow the multiple assignments case.
The second is preferable by far; the first assumes that word-splitting and pathname expansion won't make any changes to the output of xargs before export sees them.
|
0

For Zsh, I prefer the following:

function {
    setopt LOCAL_OPTIONS allexport
    local s='site.conf'
    [ -f "$s" ] && source "$s"
}

The self-executing anonymous function syntax gives you the flexibility of being able to declare local variables if needed. Combined with the ability to set options within a function scope (setopt LOCAL_OPTIONS), you also don't have to worry about those options affecting the rest of your script, after the function runs.

Comments

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.