Esto se reduce a una cuestión de cómo funciona la evaluación. Ambos ejemplos funcionan de la misma manera, el problema ocurre debido a cómo el shell (bash, aquí) expande las variables.
Cuando escribes este comando:
HOME="foo" echo $HOME
El $HOMEse expande antes de ejecutar el comando . Por lo tanto, se expande al valor original y no al nuevo en el que lo configuró para el comando. De hecho, la HOMEvariable se ha cambiado en el entorno en el que echose ejecuta el comando, sin embargo, está imprimiendo $HOMEdesde el padre.
Para ilustrar, considere esto:
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
Como puede ver arriba, el primer comando imprime el valor modificado temporalmente HOMEy el segundo imprime el original, lo que demuestra que la variable solo se modificó temporalmente. Debido a que el bash -c ...comando está encerrado entre comillas simples ( ' ') en lugar de comillas dobles ( " "), la variable no se expande y se pasa como está al nuevo proceso bash. Este nuevo proceso luego lo expande e imprime el nuevo valor en el que se ha establecido. Puede ver que esto suceda si usa set -x:
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo hello
hello
Como puede ver arriba, la variable $HOME nunca se pasa a echo. Solo ve su valor expandido. Comparar con:
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
Aquí, debido a las comillas simples, la variable y no su valor se pasan al nuevo proceso.
local.