When to use a semi-colon between environment variables and a command
Parameter and other types of expansions are performed when the command is read, before it is executed.
The first version, LANG=Ja_JP bash -c "echo $LANG"
, is a single command. After it is parsed as such, $LANG
is expanded to en_US
before anything is executed. Once bash
is finished processing the input, it forks a process, adds LANG=Ja_JP
to the environment as expected, and then executes bash -c echo en_US
.
You can prevent expansion with single quotes, i.e. LANG=Ja_JP bash -c 'echo $LANG'
outputs Ja_JP
.
Note that when you have a variable assignment as part of a command, the assignment only affects the environment of that command and not that of your shell.
The second version, LANG=Ja_JP; bash -c "echo $LANG"
is actually two separate commands executed in sequence. The first is a simple variable assignment without a command, so it affects your current shell.
Thus, your two snippets are fundamentally different despite the superficial distinction of a single ;
.
Completely off-topic, but might I recommend appending a .UTF-8
when setting LANG
. There's no good reason nowadays not to be using Unicode in the 21st century.
VAR=value; somecommand
is equivalent to
VAR=value
somecommand
These are unrelated commands executed one after the other. The first command assigns a value to the shell variable VAR
. Unless VAR
is already an environment variable, it is not exported to the environment, it remains internal to the shell. A statement export VAR
would export VAR
to the environment.
VAR=value somecommand
is a different syntax. The assignment VAR=value
is to the environment, but this assignment is only made in the execution environment of somecommand
, not for the subsequent execution of the shell.
By way of example:
# Assume neither VAR1 nor VAR2 is in the environment
VAR1=value
echo $VAR1 # displays "value"
env | grep '^VAR1=' # displays nothing
VAR2=value env | grep '^VAR2=' # displays "VAR2=value"
echo $VAR2 # displays nothing