Why is my zsh doing this?
% MYVAR="hi" echo $MYVAR
% MYVAR="$(date)" echo $MYVAR
% export MYVAR="$(pwd)"
% echo $MYVAR
/Users/theonlygusti
Why are the same-line environment variables apparently not set?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityIn the command
MYVAR="hi" echo $MYVAR
the variable MYVAR
is set to hi
in the environment of the echo
command. However, the echo
command does not use this variable. It is the current shell that expands the $MYVAR
argument on the command line before calling echo
.
Therefore, if the MYVAR
variable does not exist in the shell beforehand, that command will only output a newline character.
In your last example, you set the variable in the shell before calling echo
with the expansion of $MYVAR
on the command line. Since the variable is set to the result of $(pwd)
at that point (it does not need to be exported), the shell replaces $MYVAR
with that value before calling echo
.
The difference between
variable=value some-command
and
variable=value; some-command
or the equivalent
variable=value
some-command
is that in the first case, the variable is set to a value in the environment of some-command
, but not in the current shell, while in the second/third case, the variable is set in the current shell, and then some-command
is called. If variable
is additionally exported, then that variable would also be available in the environment of some-command
, would it want to use that variable.
Example:
$ unset -v var
Setting a variable at the same time as calling another command sets that variable in the command's environment, but not in the local environment:
$ var=1 sh -c 'printf "var is %s\n" "$var"'
var is 1
$ printf 'var is %s\n' "$var"
var is
Setting a variable in the local environment, but not exporting it sets it locally only:
$ var=1; sh -c 'printf "var is %s\n" "$var"'
var is
$ printf 'var is %s\n' "$var"
var is 1
Exporting the variable makes it available in child processes:
$ export var
$ sh -c 'printf "var is %s\n" "$var"'
var is 1
Note that
MYVAR=$(pwd)
is the same as
MYVAR=$PWD
eval
, for instance: var=1 eval echo '$var'
, and show the difference between this and the new shell. For instance, when using eval
, var=1; eval echo '$var'
would still show the value of $var
.
eval
should ideally take a single-quoted string: eval 'echo "$var"'
. In the bash
shell, you'll otherwise invoke the split+glob operation on the value of $var
(test with var='1 * 4'
in bash
). I know this user is using zsh
, but that may easily be missed by future readers that just read the answer.
echo ${MYVAR}
instead (with {} ). I don't know how it works, though. Something to do with variable expansion I think.