191

On Linux (Ubuntu 11.04 (Natty Narwhal)) in Bash, is it possible to temporarily set an environment variable that will only be different from the normal variable for the duration of the script?

For example, in a shell script, making an application that saves to HOME portable by temporarily setting HOME to a folder in the present working directory, and then launching the application.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
suchipi
  • 1,911
  • 2
  • 12
  • 3
  • 6
    It would be harder if you wanted the setting to last _beyond_ the duration of the script – Nemo Aug 20 '11 at 00:01
  • https://unix.stackexchange.com/questions/126938/why-is-setting-a-variable-before-a-command-legal-in-bash – ptim Dec 16 '21 at 01:27

3 Answers3

176
VAR1=value1 VAR2=value2 myScript args ...
Rockallite
  • 16,437
  • 7
  • 54
  • 48
  • 3
    I've done this myself numerous times to run `vblank_mode=0 glxgears`. It works, but it also says `vblank_mode=0: command not found` after running, whereas prepending `env` doesn't cause this. [testing...] Apparently zsh doesn't like it (yet still uses it correctly), but bash is fine with it. I guess I'll go with the `env` method from now on. – Chinoto Vokro Oct 26 '16 at 15:58
  • 12
    with scripts it works but how about `VAR1="hello" echo $VAR1` does not return anything? – Zibri Aug 07 '19 at 07:53
  • 6
    @Zibri it is about when the expansion is happening. Probably you can do something like that: `VAR1="hello" bash -c 'echo $VAR1'` – cybergrind Oct 01 '19 at 06:37
  • Upvoted for showing that this is possible even for multiple environment variables. – Binarus Jan 22 '20 at 22:08
  • Can we do this with `export` so the variable remains with subprocesses too? – jozxyqk Jul 01 '21 at 02:27
  • @jozxyqk As you can see from this example, you don't need to separately `export` this variable for it to be inherited by subprocesses. VAR1="whoa" bash -c 'sh -c "env | grep VAR1"'` – tripleee Jul 01 '21 at 03:43
  • My mistake. I had this at the start of a pipe, which doesn't work. https://stackoverflow.com/questions/10856129/setting-an-environment-variable-before-a-command-in-bash-is-not-working-for-the. Thanks, @tripleee! – jozxyqk Jul 01 '21 at 04:02
82
env VAR=value myScript args ...
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 24
    Or `VAR=value myScript args ...` – Rockallite Jan 26 '14 at 06:25
  • 13
    1. How come `PATH=$PATH:XYZ echo $PATH | grep XYZ` doesn't have any output though? 2. What is the difference between using and not using `env`? – qubodup Mar 23 '15 at 01:27
  • 28
    because the shell expands the PATH variable **before** executing the echo command. You need to delay that expansion. One way: `PATH=$PATH:XYZ sh -c 'echo $PATH' | grep XYZ` -- the single quotes are the key here – glenn jackman Mar 23 '15 at 10:19
  • 19
    What is the difference between using `env` and not using it? – Mohammed Noureldin Jan 01 '18 at 23:18
  • This doesn't appear to work in a oneliner like `IFS=$'\n' for l in lines; do ... done` – drevicko Jul 08 '19 at 01:38
  • @drevicko I have noticed the same – Zibri Aug 07 '19 at 07:54
  • 1
    @MohammedNoureldin not a full answer, but in my own experience, depending on shell type, using without `env` gives an error and other shells don't give an error, so I guess it's mostly safer to always use with `env`. – elquimista Nov 19 '19 at 21:15
  • 1
    As other commenters have remarked, `env` is more versatile in that you can specify it in places where you don't have access to the shell's full syntax, and in places where you are required to enter a single command. – tripleee Jul 01 '21 at 03:45
  • @drevicko You can't affect the environment of the _current_ shell with `env`. – tripleee Jul 01 '21 at 03:46
45

WARNING --- READ THE COMMENTS.


Just put

export HOME=/blah/whatever

at the point in the script where you want the change to happen. Since each process has its own set of environment variables, this definition will automatically cease to have any significance when the script terminates (and with it the instance of bash that has a changed environment).

Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
hmakholm left over Monica
  • 23,074
  • 3
  • 51
  • 73
  • 15
    That's misleading. `export` will pass the variable to subshells, but it doesn't control the parent shell. If you're writing a script that begins with "#!/bin/sh" or the like, ANY variable you set will disappear when the script exits. – brightlancer Aug 20 '11 at 00:27
  • 1
    @brightlancer, that is true but does not appear to contradict anything I wrote. (With the exception of the possibility that the script might start a background process, but I think that is beyond the OP's level of sophistication and would only confuse). – hmakholm left over Monica Aug 20 '11 at 00:29
  • 5
    The export is unnecessary. Also, your answer only works if his script invokes an interpreter (#!/bin/sh or the like). If his "script" doesn't, then what you just told him will persist beyond the end of his script. That is why I said your answer was misleading - it might be correct, it might not, but it's definitely got a part that's unnecessary and confusing because it may cause someone to think "export" is the necessary element he was looking for. – brightlancer Aug 20 '11 at 18:10
  • 9
    @brightlancer: The export is necessary if the OP's script invokes sub-scripts that themselves depend on $HOME, and I dared not assume _that_ was not the case. Furthermore, bash will spawn a subshell to run a script even if the script has no shebang line but is just a text file with the execute bit set. Try it -- variable assignments in the script are not visible in the shell you invoke it from. It's only if you explicitly `source` the script that it will be executed by the same shell that you type the command into. – hmakholm left over Monica Aug 20 '11 at 18:47
  • On all of those counts you're right, except where you assumed how he was running his script and what part the export played in that. Which is why I said it was misleading. – brightlancer Aug 20 '11 at 19:24
  • 4
    @brightlancer: The export is necessary if he wants `$HOME` to be inherited by any commands executed from the script. And if he doesn't, and the setting of `$HOME` is only for the benefit of the script itself, then he'd probably be better off modifying the script so it refers to something other than `$HOME`. – Keith Thompson Aug 20 '11 at 20:14
  • In my case I needed a second JAVA_HOME, only for tests. Worked!! Thanks! – JRichardsz Dec 14 '17 at 14:44
  • for sudo it's not working `sudo MINIO_ACCESS_KEY=1234567890 MINIO_SECRET_KEY=1234567890 ./minio server /minio` – Николай Мишин Dec 09 '20 at 12:04