Every so often I'll bash out a bash script and it strikes me there are a few ways of setting a variable:
key=value
env key=value
export key=value
When you're inside a script or a single command (for instance, I'll often chain a variable with a Wine launcher to set the right Wine prefix) these seem to be completely interchangeable but surely that can't be the case.
What's the difference between these three methods and can you give me an example of when I would specifically want to use each one?
Definitely related to What is the difference between `VAR=...` and `export VAR=...`? but I want to know how env
fits into this too, and some examples showing the benefits of each would be nice too :)
Let us consider a specific example. The
grep
command uses an environment variable calledGREP_OPTIONS
to set default options.Now. Given that the file
test.txt
contains the following lines:running the command
grep one test.txt
will returnIf you run grep with the
-v
option, it will return the non-matching lines, so the output will beWe will now try to set the option with an environmental variable.
Environment variables set without
export
will not be inherited in the environment of the commands you are calling.The result:
Obviously, the option
-v
did not get passed togrep
.You want to use this form when you are setting a variable only for the shell to use, for example in
for i in * ; do
you do not want to export$i
.However, the variable is passed on to the environment of that particular command line, so you can do
which will return the expected
You use this form to temporarily change the environment of this particular instance of the program launched.
Exporting a variable causes the variable to be inherited:
returns now
This is the most common way of setting variables for use of subsequently started processes in a shell
This was all done in bash.
export
is a bash builtin;VAR=whatever
is bash syntax.env
, on another hand, is a program in itself. Whenenv
is called, following things happen:env
gets executed as a new processenv
modifies the environment, andenv
process is replaced by thecommand
process.Example:
This command will launch two new processes: (i) env and (ii) grep (actually, the second process will replace the first one). From the point of view of the
grep
process, the result is exactly the same as runningHowever, you can use this idiom if you are outside of bash or don't want to launch another shell (for example, when you are using the
exec()
family of functions rather than thesystem()
call).Additional note on
#!/usr/bin/env
This is also why the idiom
#!/usr/bin/env interpreter
is used rather than#!/usr/bin/interpreter
.env
does not require a full path to a program, because it uses theexecvp()
function which searches through thePATH
variable just like a shell does, and then replaces itself by the command run. Thus, it can be used to find out where an interpreter (like perl or python) "sits" on the path.It also means that by modifying the current path you can influence which python variant will be called. This makes the following possible:
instead of running Python, will result in