3

In my Bash terminal, I regularly execute a chain of commands. For example:

cmd1 && cmd2 && cmd3

Now, I want to define an environment variable which is applied to all three commands and which only scoped to those commands. I tried:

MY_VAR=abc cmd1 && cmd2 && cmd3

But it seems that now only cmd1 sees MY_VAR.

Is there a way to apply the environment variable to all three commands? I know I could export in advance, but I prefer to declare the environment variable locally in an ad-hoc fashion, so it will never impact subsequent commands.

It it matters, I am using urxvt as terminal emulator.

Koller
  • 33
  • 4
  • According to the SHELL GRAMMAR section of the [bash man page](https://linux.die.net/man/1/bash), this type of variable assignment is part of a "simple command", and hence cannot be applied to compound commands (like "lists" of commands separated by `&&` or `;`). – Gordon Davisson Jul 27 '19 at 09:16
  • 3
    `(export MY_VAR=abc; cmd1 && cmd2 && cmd3)` – Cyrus Jul 27 '19 at 13:17

4 Answers4

4

Repeat it: MY_VAR=abc cmd1 && MY_VAR=abc cmd2 && MY_VAR=abc cmd3

Or use a subshell:

   # wrapper subshell for the commands
   cmds () 
   {
      cmd1 && cmd2 && cmd3
   }

   # invoke it
   MY_VAR=abc cmds

If you need to enter the whole thing in one go, do:

   cmds() { cmd1 && cmd2 && cmd3; }; MY_VAR=abc cmds
user268396
  • 11,576
  • 2
  • 31
  • 26
  • Notice the line breaks in the subshell definition? If you need to enter it in one go you can condense the subshell like this: `cmds () { cmd1 && cmd2 && cmd3; }; MY_VAR=abc cmds` – user268396 Jul 27 '19 at 09:15
  • Appreciated, this is what I needed! – Koller Jul 27 '19 at 09:20
  • 1
    This is more complicated than it looks. The function does not run in a subshell (I tested in bash, zsh, dash, and ksh). The variable is temporarily set in the shell during the function in all tested shells, but is only exported to commands run in the function in bash and zsh. As a result, this does not work in dash or ksh. (There's a bash tag in the question, but for anyone else reading this...) – Gordon Davisson Jul 27 '19 at 19:19
0

You can try this:

export MY_VAR="abc"
cmd1 && cmd2 && cmd3
unset MY_VAR          # only nessesary if you want to remove the variable again
UtLox
  • 3,744
  • 2
  • 10
  • 13
0

The way to do it is:

MY_VAR=abc; cmd1 && cmd2 && cmd3

What makes the difference is the colon after the assignment.

Without the colon ;, MY_VAR=abc cmd1 && ... this cause the assignment to be part of the cmd1 element of the conditional expression. Anything at the other side of the logical AND: && can not see the local environment of the other condition elements.

Léa Gris
  • 17,497
  • 4
  • 32
  • 41
  • 1
    That would require `MY_VAR` to be exported. – Ed Morton Jul 27 '19 at 15:25
  • @EdMorton, really. I tried it before to make sure. An export is needed for the variable to propagate within the scope of other processes/shells. There the colon `;` only separate blocks of commands but everything is already in the scope of current shell. So no need to export. – Léa Gris Jul 27 '19 at 17:33
  • 2
    Put `echo "$MY_VAR"` in `tst.sh` then run `MY_VAR=abc ./tst.sh` and it'll output `abc` while `MY_VAR=abc; ./tst.sh` will output a null string. – Ed Morton Jul 27 '19 at 17:39
  • 1
    @EdMorton this because `./tst.sh` is spawning another shell process. Now I get it ^^ – Léa Gris Jul 27 '19 at 18:00
  • id suggest `MY_VAR=abc && cmd1 && cmd2 && cmd3` instead. && ensures that execution environment for those 4 commands is the same – Blue Print Jul 12 '23 at 12:43
  • I think that the author of this post has misintended`&&` for `;`. `&&` allows commands to share working environment but `;` doesnt. – Blue Print Jul 12 '23 at 12:48
0

I've created a simple script to echo my variable to try and simulate a command. Also declared 1 "global environment variable" with the export command.

#!/bin/bash
echo $ABC

Input

$ export ABC=globalEnvironmentVariable
$ (ABC=localGroupVariable; ./test.sh && ./test.sh) && ABC=commandVariable ./test.sh && ./test.sh

Output

localGroupVariable
localGroupVariable
commandVariable
globalEnvironmentVariable
Zauxst
  • 41
  • 1
  • 4