To bring the existing answers together with an important clarification:
As stated, the problem with NAME=sam echo "$NAME"
is that $NAME
gets expanded by the current shell before assignment NAME=sam
takes effect.
Solutions that preserve the original semantics (of the (ineffective) solution attempt NAME=sam echo "$NAME"
):
Use either eval
[1]
(as in the question itself), or printenv
(as added by Aaron McDaid to heemayl's answer), or bash -c
(from Ljm Dullaart's answer), in descending order of efficiency:
NAME=sam eval 'echo "$NAME"' # use `eval` only if you fully control the command string
NAME=sam printenv NAME
NAME=sam bash -c 'echo "$NAME"'
printenv
is not a POSIX utility, but it is available on both Linux and macOS/BSD.
What this style of invocation (<var>=<name> cmd ...
) does is to define NAME
:
In other words: NAME
only exists for the command being invoked, and has no effect on the current shell (if no variable named NAME
existed before, there will be none after; a preexisting NAME
variable remains unchanged).
POSIX defines the rules for this kind of invocation in its Command Search and Execution chapter.
The following solutions work very differently (from heemayl's answer):
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
While they produce the same output, they instead define:
NAME
(only) rather than an environment variable
echo
were a command that relied on environment variable NAME
, it wouldn't be defined (or potentially defined differently from earlier).Note that every environment variable is also exposed as a shell variable, but the inverse is not true: shell variables are only visible to the current shell and its subshells, but not to child processes, such as external utilities and (non-sourced) scripts (unless they're marked as environment variables with export
or declare -x
).
[1] Technically, bash
is in violation of POSIX here (as is zsh
): Since eval
is a special shell built-in, the preceding NAME=sam
assignment should cause the the variable $NAME
to remain in scope after the command finishes, but that's not what happens.
However, when you run bash
in POSIX compatibility mode, it is compliant.
dash
and ksh
are always compliant.
The exact rules are complicated, and some aspects are left up to the implementations to decide; again, see Command Search and Execution.
Also, the usual disclaimer applies: Use eval
only on input you fully control or implicitly trust.