What is this shell/Bash syntax: someVariable=someValue someCommand
This is equivalent to:
( export someVariable=something; command )
This makes someVariable
an environment variable, with the assigned value, but only for the command being run.
Here are the relevant parts of the bash
manual:
Simple Commands
A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections, and terminated by a control operator. The first word specifies the command to be executed, and is passed as argument zero. The remaining words are passed as arguments to the invoked command.
(...)
Simple Command Expansion
If no command name results [from command expansion], the variable assignments affect the current shell environment. Otherwise, the variables are added to the environment of the executed command and do not affect the current shell environment.
Note: bear in mind that this is not specific to bash
, but specified by POSIX.
Edit - Summarized discussion from comments in the answer
The reason BAZ=JAKE echo $BAZ
, doesn't print JAKE is because variable substitution is done before anything else. If you by-pass variable substitution, this behaves as expected:
$ echo_baz() { echo "[$BAZ]"; }
$ BAZ=Jake echo_baz
[Jake]
$ echo_baz
[]
These are variable assignments in the context of simple commands. As xhienne has mentioned, for external commands they are equivalent to exporting the assigned value(s) for the duration of the command.
In your examples you're using a built-in command, so the behaviour isn't quite the same: the assignments affect the current environment, but whether the effect lasts after the execution of the built-in command is unspecified. To understand your examples, you need to know that parameter expansion happens before variables are handled; thus with
BAZ=jake echo $BAZ
the shell first expands $BAZ
(resulting in nothing), then sets BAZ
to jake
, and finally runs
echo
which prints an empty line. (Then the shell forgets BAZ
as your subsequent echo $BAZ
shows.)
BAZ=jake; echo $BAZ
is interpreted as two commands: first the BAZ
variable is set in the current environment, then echo $BAZ
is expanded to echo jake
and executed.
There are a few key things that happen here:
As explained in bash reference manual, Simple Command Expansion, section "If no command name results, the variable assignments affect the current shell environment. Otherwise, the variables are added to the environment of the executed command and do not affect the current shell environment." Thus, when you say
var="something" command arg1 arg2
, the command will run withvar
being in command's environment and disappearing aftercommand
exits. Demonstration of this is simple - access the command's environment from within the command:$ BAZ="jake" python -c "import os; print os.environ['BAZ']" jake
This is nothing to be surprised about. Such syntax is frequently used to run programs with modified environment. My fellow unix.stackexchange.com and askubuntu.com users will recognize this example: if user uses German locale, and you only speak in English, you can ask them to reproduce whatever issue they're having and obtain output in English like so:
LC_ALL=C command
Note also that environment access isn't specific to
python
. It can be done withC
or any other programming language. It just so happened to be my "weapon of choice" right now and only used for this demo.The variable expansion occurs before anything runs. Thus, when you run something like
BAZ="foo" echo $BAZ
, the shell looks into its environment first, finds no variable BAZ there , and thus leaves$BAZ
empty. Simple demonstration of that is:$ BAZ="jake" python -c "import sys; print 'ARG:',sys.argv[1]" $BAZ ARG: Traceback (most recent call last): File "<string>", line 1, in <module> IndexError: list index out of range
It's important to also note, the distinction from BAZ=jake; echo $BAZ
which is two separate command statements and here BAZ=jake
will stay in shell's environment. The use case depends on your intentions. If you intend running more than one program that needs such variable, it might be desirable to export
such variable. If you only need it for this one specific time, then preceding variable assignments are might be preferable.