Setting environment variable for one program call in bash using env
A sanity check with no expansion at all is HELLO=’Hello World’ env | grep HELLO which does what is requested but is much less useful in practice than the accepted answer.
5 Answers 5
It’s because in your first case, your current shell expands the $HELLO variable before running the commands. And there’s no HELLO variable set in your current shell.
env HELLO='Hello World' echo $HELLO
- expand any variables given, in this case $HELLO
- run env with the 3 arguments ‘HELLO=Hello World’ , ‘echo’ and » (an empty string, since there’s no HELLO variable set in the current shell)
- The env command will run and set the HELLO=’Hello World’ in its environment
- env will run echo with the argument » (an empty string)
As you see, the current shell expanded the $HELLO variable, which isn’t set.
HELLO='Hello World' bash -c 'echo $HELLO'
- set the variable HELLO=’Hello World for the following command
- run bash with the 2 arguments ‘-c’ and ‘echo $HELLO’
- since the last argument is enclosed in single quotes, nothing inside it is expanded
- the new bash in turn will run the command echo $HELLO
- To run echo $HELLO in the new bash sub-shell, bash first expands anything it can, $HELLO in this case, and the parent shell set that to Hello World for us.
- The subshell runs echo ‘Hello World’
If you tried to do e.g. this:
env HELLO='Hello World' echo '$HELLO'
- The current shell would expand anything it can, which is nothing since $HELLO is enclosed in single quotes
- run env with the 3 arguments ‘HELLO=Hello World’ , ‘echo’ and ‘$HELLO’
- The env command will run and set the HELLO=’Hello World’ in its environment
- env will run echo with the argument ‘$HELLO’
In this case, there’s no shell that will expand the $HELLO , so echo receives the string $HELLO and prints out that. Variable expansion is done by shells only.
+1, Just a nitpick: env HELLO=’Hello World’ echo $HELLO will get expanded to env HELLO=’Hello World’ echo (no args to echo.). env HELLO=’Hello World’ echo «$HELLO» will get expanded to env HELLO=’Hello World’ echo » (empty string arg to echo.)
I think what happens is similar to this situation in which I was also puzzled.
In a nutshell, the variable expansion in the first case is done by the current shell which doesn’t have $HELLO in its environment. In the second case, though, single quotes prevent the current shell from doing the variable expansion, so everything works as expected.
Note how changing single quotes to double quotes prevents this command from working the way you want:
HELLO='Hello World' bash -c "echo $HELLO"
Now this will be failing for the same reason as the first command in your question.
Setting environment variables in Linux using Bash
What is the equivalent to the tcsh setenv function in Bash? Is there a direct analog? The environment variables are for locating the executable.
5 Answers 5
export VAR=value will set VAR to value. Enclose it in single quotes if you want spaces, like export VAR=’my val’ . If you want the variable to be interpolated, use double quotes, like export VAR=»$MY_OTHER_VAR» .
PS: no need for the double quotes in the last one. The shell does not perform word splitting for variable assignments.
Just for the beginners. I had not understood it directly, here in normal English: interpolate «$X» means here that you already have a variable X that is filled with a value, e.g. «A», and you want to read out that value «A» first, and then assign this value as the value of VAR. You do not want VAR to be a string of «$X» here of course. And then the comment above seems also logical, that you will not even need the «». And for a direct assignment of «A», use ‘A’. Please correct me if I got it wrong.
The reason people often suggest writing
is that the longer form works in more different shells than the short form. If you know you’re dealing with bash , either works fine, of course.
Set a local and environment variable using Bash on Linux
Check for a local or environment variables for a variable called LOL in Bash:
el@server /home/el $ set | grep LOL el@server /home/el $ el@server /home/el $ env | grep LOL el@server /home/el $
Sanity check, no local or environment variable called LOL.
Set a local variable called LOL in local, but not environment. So set it:
el@server /home/el $ LOL="so wow much code" el@server /home/el $ set | grep LOL LOL='so wow much code' el@server /home/el $ env | grep LOL el@server /home/el $
Variable ‘LOL’ exists in local variables, but not environment variables. LOL will disappear if you restart the terminal, logout/login or run exec bash .
Set a local variable, and then clear out all local variables in Bash
el@server /home/el $ LOL="so wow much code" el@server /home/el $ set | grep LOL LOL='so wow much code' el@server /home/el $ exec bash el@server /home/el $ set | grep LOL el@server /home/el $
You could also just unset the one variable:
el@server /home/el $ LOL="so wow much code" el@server /home/el $ set | grep LOL LOL='so wow much code' el@server /home/el $ unset LOL el@server /home/el $ set | grep LOL el@server /home/el $
Local variable LOL is gone.
Promote a local variable to an environment variable:
el@server /home/el $ DOGE="such variable" el@server /home/el $ export DOGE el@server /home/el $ set | grep DOGE DOGE='such variable' el@server /home/el $ env | grep DOGE DOGE=such variable
Note that exporting makes it show up as both a local variable and an environment variable.
Exported variable DOGE above survives a Bash reset:
el@server /home/el $ exec bash el@server /home/el $ env | grep DOGE DOGE=such variable el@server /home/el $ set | grep DOGE DOGE='such variable'
Unset all environment variables:
You have to pull out a can of Chuck Norris to reset all environment variables without a logout/login:
el@server /home/el $ export CAN="chuck norris" el@server /home/el $ env | grep CAN CAN=chuck norris el@server /home/el $ set | grep CAN CAN='chuck norris' el@server /home/el $ env -i bash el@server /home/el $ set | grep CAN el@server /home/el $ env | grep CAN
You created an environment variable, and then reset the terminal to get rid of them.
Or you could set and unset an environment variable manually like this:
el@server /home/el $ export FOO="bar" el@server /home/el $ env | grep FOO FOO=bar el@server /home/el $ unset FOO el@server /home/el $ env | grep FOO el@server /home/el $
Run program with environment set to variables in a file
I would like to run a program (in this case Python) with only the environment variables defined in a file, say vars.env :
import os print os.environ
$ env -i FOO=bar X=12 python env.py
However what I would like to do is load the environment from my vars.env file when running the script. How can I accomplish this? EDIT: One thing that I could do is cat this env file, like env -i `cat vars.env` python env.py but I would prefer to be able to source it in some way.
I don’t understand the question: you seem to already have found a way to “run program with environment set to variables in a file”. Is the question how to do that from inside the Python script, so that you can directly run /path/to/myscript.py ?
3 Answers 3
Given the file you show, you should be able to do:
(set -f ; IFS=' ' ; env - $(cat /path/to/file) /path/to/your/program )
If it doesn’t work then it is only because you need to format your environment file first. Here’s an example:
(set -f ; IFS=' ' ; env - $(cat) printenv ) <<\ENV variable1=value1 variable2=value2 variable3=value3 an$d s'om\e m"ore ENV ###OUTPUT### variable1=value1 variable2=value2 variable3=value3 an$d s'om\e m"ore
I at first thought you could do it through the shell - but it will probably set some of its own environment before calling your program. But I can at least demonstrate that the arguments are assigned correctly:
(set -f; IFS=' ' ; env - $(cat) sh -c 'echo "$variable3"' ) <<\ENV variable1=value1 variable2=value2 variable3=value3 an$d s'om\e m"ore ENV ###OUTPUT### value3 an$d s'om\e m"ore
Still, if you would prefer to source it, here's how you can using the shell:
Notice that I removed the $IFS stuff - that's not necessary this way - but I did have to get specific about the quotes in the file. Here I'm essentially .dot sourcing stdin - reading the |pipe as input - but you can use any file. I use set -a before reading the input file to set the --allexport option.
That is a result of using bash 's sh - it adds $PWD , $SHLVL and $_ . With dash it is a little better. And dash doesn't add a bunch of exports either, so you can specify the -a parameter on the command line: