When I run PATH=abc:$PATH echo $PATH, I get the old value for PATH, not abc:PATH

Why is this? How can I get abc:$PATH?

Edit: How about for PATH=/mybin:$PATH which python if /mybin has a python executable?


When you run

PATH=abc:$PATH echo $PATH

or, in the more general case,

variable=value utility

then the variable is set in environment of the utility (but not in the current environment).

However, when your command line is parsed, the value of the PATH variable is taken from the current environment.

You would have to set the variable in the environment where the variable is expanded. You may do this either either by separating it into two steps, as in

PATH=abc:$PATH; echo "$PATH"

which would set PATH in the current environment and then execute echo "$PATH", or set the variable for a child shell, as in

PATH=abc:$PATH sh -c 'echo "$PATH"'

which would set the PATH variable within sh -c, but not in the current shell.

In your second example,

PATH=/mybin:$PATH which python

the which utility will probably say that python is found in /mybin since you modify PATH in its environment. Notice how PATH is never expanded in the current environment here, but internally by which.

Incidentally, which python is better (more portably) written command -v python (see "Why not use "which"? What to use then?").

Just a quick reflection on your title, where you say "ENV variable". The ENV variable, even if this was not what you meant, happens to be an environment variable that some implementations of sh (and some other shells) use. If its value is the name of a file, that file will be sourced before starting an interactive shell session. bash has a BASH_ENV variable which works the same way, but for non-interactive shells.

  • Whether parameters in the argument list are expanded in the parent or the child is an implementation detail and not required. What POSIX requires is that parameters in the argument list are expanded before the environment is set up. See explanation in my answer.
    – schily
    May 25 '18 at 8:05

Perform the substitution in a subshell instead of the current shell.

PATH=abc:$PATH sh -c 'echo $PATH'

The reason is that the expansion for echo $PATH happens before the modified environment is created.

You may like to call:

PATH=abc:$PATH env

to see that the environment for the command indeed is modified.

Since the expansion of the echo argument in

PATH=abc:$PATH echo $PATH

happens before the new environment is set up, you need to split things up into two commands:

(PATH=abc:$PATH; echo $PATH)

does what you like. The sub shell () is needed to prevent the environment change to survive the lifetime of the echo command.

Not the answer you're looking for? Browse other questions tagged or ask your own question.