user1934428
user1934428

Reputation: 22225

Can I set in Zsh an environment variable just for a subshell or a compound command?

I would like to run two commands, x and y, and define an environmentvariable V just for these too. Is there an easy way to do it in zsh? The "bash-like" solution, i.e.

(export V=myvalue; x; y)

is cumbersome and works only with a subshell, not a compound. However, the following two versions are syntactically invalid:

V=myvalue ( x ; y ) # No!
V=myvalue { x ; y } # No!No!No!

Upvotes: 1

Views: 3606

Answers (2)

Adaephon
Adaephon

Reputation: 18329

It is not possible without at least some extra code.

The modification of the environment by prepending variable assignments works only with Simple Commands. Meaning that the first word after the variable assignments needs to be the name of a simple (as in "not complex") command. Complex commands include { list } and ( list ) contstructs. (See the documentation on Complex Commands for a complete list)

If you want to modify the environment for a specific list of commands without changing the environment of your current shell, I can think of two ways to achive that

  1. As mentioned in the question there is the rather straight-forward solution by runnig a subshell and exporting the variable explicitly:

    (export V=myvalue; x; y)
    
  2. You can use eval to avoid creating a subshell:

    V=myvalue eval "x; y"
    V=myvalue eval x\; y
    

    This also saves three to four characters compared to the first solution. The main drawback seems to be that completion does not work very well inside the argument list for eval.

Upvotes: 3

chepner
chepner

Reputation: 530833

It's a little longer, but not much. You can define a function, then immediately call it as a simple command.

f () { x; y; }; V=foo f

Or, you could do a local export with an anonymous function:

() { local -x V=myvalue; x; y }

Upvotes: 1

Related Questions