Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print / echo environment variables?

Tags:

bash

eval

How do I print the environment variable just being set?

NAME=sam echo "$NAME" # empty 

You can see here using eval it works. Is this the way?

NAME=sam eval 'echo $NAME' # => sam 
like image 381
ThomasReggi Avatar asked Oct 14 '16 19:10

ThomasReggi


People also ask

How do I print all environment variables?

Using the printenv Command Or, if we run the command without arguments, it will display all environment variables of the current shell.

How do I echo the env variable in CMD?

Select Start > All Programs > Accessories > Command Prompt. In the command window that opens, enter echo %VARIABLE%. Replace VARIABLE with the name of the environment variable.


2 Answers

These need to go as different commands e.g.:

NAME=sam; echo "$NAME" NAME=sam && echo "$NAME" 

The expansion $NAME to empty string is done by the shell earlier, before running echo, so at the time the NAME variable is passed to the echo command's environment, the expansion is already done (to null string).

To get the same result in one command:

NAME=sam printenv NAME 
like image 161
heemayl Avatar answered Oct 02 '22 13:10

heemayl


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:

  • as an environment variable
  • that is only defined for the command being invoked.

In other words: NAME only exists for the command (child process) 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 (quoted from heemayl's answer):

NAME=sam; echo "$NAME" NAME=sam && echo "$NAME" 

While they produce the same output, they instead define:

  • a shell variable NAME (only) rather than an environment variable
    • if echo were a command that relied on environment variable NAME, it wouldn't be defined (or potentially defined differently from earlier).
  • that lives on after the command.

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 shell variables are designated as environment variables (too) 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.

like image 22
mklement0 Avatar answered Oct 02 '22 12:10

mklement0