Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting environment variable for one program call in bash using env

I am trying to invoke a shell command with a modified environment via the command env.

According to the manual

env HELLO='Hello World' echo $HELLO 

should echo Hello World, but it doesn't. If I do

HELLO='Hello World' bash -c 'echo $HELLO' 

it prints Hello World as expected (thanks to this answer for this info).

What am I missing here?

Cheers, Niklas

like image 456
Niklas Avatar asked Dec 21 '12 22:12

Niklas


People also ask

How do I set an environment variable in bash?

The easiest way to set environment variables in Bash is to use the “export” keyword followed by the variable name, an equal sign and the value to be assigned to the environment variable.

How do I set an environment variable in a program?

To set (or change) a environment variable, use command " set varname=value ". There shall be no spaces before and after the '=' sign. To unset an environment variable, use " set varname= ", i.e., set it to an empty string.

How do I set an environment variable in shell?

To set an environment variable everytime, use the export command in the . bashrc file (or the appropriate initialization file for your shell). To set an environment variable from a script, use the export command in the script, and then source the script. If you execute the script it will not work.


2 Answers

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 

will do this:

  • 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' 

will do this:

  • 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.

like image 131
nos Avatar answered Sep 20 '22 08:09

nos


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.

like image 28
Lev Levitsky Avatar answered Sep 22 '22 08:09

Lev Levitsky