Bash – Why does FOO=bar; export the variable into the environment

bashenvironment-variablesshell

If I run

FOO=bar docker run -it -e FOO=$FOO debian env

That environment variable is not set in the command output for the env command.

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=03f3b59c0aab
TERM=xterm
FOO=
HOME=/root

But if I run

FOO=bar; docker run -i -t --rm -e FOO=$FOO debian:stable-slim env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=672bfdcde93c
TERM=xterm
FOO=bar
HOME=/root

Then the variable is available from the container and also exported into my current shell environment.

echo $FOO
bar

I expect this behavior with export FOO=bar but why does that happen with ; too?

Best Answer

No, FOO=bar; does not export the variable into my environment

A var is set in the (present) environment only if it was previously exported:

$ export foo
$ foo=bar
$ env | grep foo
foo=bar

A variable is set in the environment of a command when it is placed before the command. Like foo=bar command. And it only exists while the command runs.

$ foo=bar bash -c 'echo "foo is = $foo"'
foo is = bar

The var is not set for the command line (in the present shell):

$ foo=bar bash -c echo\ $foo

Above, the value of $foo is replaced with nothing by the present running shell, thus: no output.

Your command:

$ FOO=bar docker run -it -e FOO=$FOO debian env

is converted to the actual string:

$ FOO=bar docker run -it -e FOO= debian env

by the present running shell.

If, instead, you set the variable (in the present running shell) with foo=bar before running the command, the line will be converted to:

$ FOO=bar; docker run -it -e FOO=bar debian env

A variable set to the environment of a command is erased when the command returns:

$ foo=bar bash -c 'echo'; echo "foo was erased: \"$foo\""

Except when the command is a builtin in some conditions/shells:

$ ksh -c 'foo=bar typeset baz=quuz; echo $foo'
bar
Related Question