This comes down to a question of how evaluation works. Both examples work in the same way, the problem happens because of how the shell (bash, here) expands variables.
When you write this command:
HOME="foo" echo $HOME
The $HOME
is expanded before the command is run. Therefore, it is expanded to the original value and not the new one you have set it to for the command. The HOME
variable has indeed been changed in the environment that the echo
command is running in, however, you are printing the $HOME
from the parent.
To illustrate, consider this:
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
As you can see above, the first command prints the temporarily changed value of HOME
and the second prints the original, demonstrating that the variable was only changed temporarily. Because the bash -c ...
command is enclosed in single quotes (' '
) instead of double ones (" "
), the variable is not expanded and is passed as-is to the new bash process. This new process then expands it and prints the new value it has been set to. You can see this happen if you use set -x
:
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo /home/terdon
/home/terdon
As you can see above, the variable $HOME
is never passed to echo
. It only sees its expanded value. Compare with:
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
Here, because of the single quotes, the variable and not its value are passed to the new process.
local
. – user23013 Feb 28 '16 at 18:49eval
solution be avoided? – Feb 29 '16 at 02:10