Reputation: 26125
I have a file .env
containing environment variables, e.g.:
TZ=UTC
NODE_ENV=development
Then, in my Bash scripts, I use:
set -o allexport; source .env; set +o allexport
This loads all the environment variables from .env
.
However, if I manually pass environment variables to the script, they get overwritten by source
. E.g. if I run NODE_ENV=production ./script.sh
, I'd like it to keep NODE_ENV=production
instead of using NODE_ENV=development
from .env
. How could I do this?
I'm using Ubuntu 20
Upvotes: 11
Views: 8838
Reputation: 22247
You have to consider the following cases:
A variable X is already defined, and the sourced file should then not touch it.
A variable X is already defined, and the sourced file should then ensure that it is put into the environment.
A variable X is not yet defined, and the sourced file then should create it.
A variable X is not yet defined, and the sourced file then should create it and put it into the environment.
If you want 1+3, this is the simplest:
: ${X:=value}
The :
is simply the bash no-op command and the :=
ensures that X
gets the value if it is not defined yet. The export status (i.e. in environment or not in environment) is not affected.
If you want the combination 2+4, you could do either
export X=${X:-value}
or
: ${X:=value}
export X
The export
statement ensures that the variable is in the environment afterwards, even if it was not in the environment before.
For my taste, the latter variant is more verbose, but clearer to read.
In theory you could also ask for the combination 1+3, i.e. not modify the environmental state of the variable, if it is defined already, but create it in the environment, if it is not defined. I can't think of a reasonable use case for this, but if you need, I can amend my answer and provide a solution for this as well.
Upvotes: 3
Reputation: 141235
Store environment "for later", source the file, then restore environment.
curenv=$(declare -p -x)
source .env
eval "$curenv"
Upvotes: 19
Reputation: 11036
You can't because the source
command is invoked after passing external variables.
To accomplish that a workaround may require some coding:
source
command..env
file content and parse it into an associative array.Upvotes: 2
Reputation: 50775
I don't think it is. But you can modify your .env file as follows to prevent it from overwriting NODE_ENV
.
TZ=UTC
NODE_ENV=${NODE_ENV:-development}
Upvotes: 5