25

I use Ubuntu 16.04 with the native Bash on it.

I'm not sure if executing

#!/bin/bash
myFunc() {
    export myVar="myVal"
}
myFunc

equals in any sense, to just executing export myVar="myVal".

Of course, a global variable should usually be declared outside of a function (a matter of convention I assume, even if technically possible) but I do wonder about the more exotic cases where one writes some very general function and wants a variable inside it to still be available to everything, anywhere.

Would export of a variable inside a function, be identical to exporting it globally, directly in the CLI, making it available to everything in the shell (all subshells, and functions inside them)?

2 Answers 2

27

Your script creates an environment variable, myVar, in the environment of the script. The script, as it is currently presented, is functionally exactly equivalent to

#!/bin/bash

export myVar="myVal"

The fact that the export happens in the function body is not relevant to the scope of the environment variable (in this case). It will start to exist as soon as the function is called.

The variable will be available in the script's environment and in the environment of any other process started from the script after the function call.

The variable will not exist in the parent process' environment (the interactive shell that you run the script from), unless the script is sourced (with . or source) in which case the whole script will be executing in the interactive shell's environment (which is the purpose of "sourcing" a shell file).

Without the function call itself:

myFunc() {
    export myVar="myVal"
}

Sourcing this file would place myFunc in the environment of the calling shell. Calling the function would then create the environment variable.

See also the question What scopes can shell variables have?

8
  • 4
    Note regarding subshells - If the function with the export myvar is called inside a ( subshell ), then the variable will still be unavailable in the parent scope.
    – Noam Manos
    Aug 23, 2020 at 18:31
  • What didn't work for me if i wrapped the export in (set -x export MY_VAR=...)
    – User Rebo
    Dec 22, 2020 at 11:18
  • @UserRebo It's unclear what you want to do. The exported variable will only be visible inside the subshell, and when the subshell terminates it will be gone. This is usually the effect one wants with an explicit subshell like this. Likewise, the effect of the set -x will also be limited the subshell. Dec 22, 2020 at 12:09
  • Only wanted to make a note for other users. The set -x will prevent exporting variables in any scope. Didn't really refer to the subshell.
    – User Rebo
    Dec 22, 2020 at 12:15
  • 2
    @UserRebo Ah, now I see! You need ; (or a newline) between set -x and export. They are two separate commands. What you wrote originally, set -x export var=value would set $1 to the string export, and $2 to the string variable=value. I didn't spot the missing ; as it was such an odd command to give. Dec 22, 2020 at 12:44
4

If using a function that exports a variable, make sure not to call it within a subshell e.g.

( export_var_func )  # Variable will NOT be exported outside

It will also happen if piping the function, since pipe uses subshell.

For example piping into tee:

export_var_func | tee my.log # Variable will NOT be exported outside

To avoid the pipe subshell, use redirection instead:

export_var_func > >(tee func.log) # Variable WILL be exported outside
1
  • +1 Awesome, I was almost giving up when I found your "instead" suggestion. It did the trick. Besides, it may not be precisely the init question, but it gives a more complete answer. It should be promoted as the right answer.
    – voiski
    Nov 3, 2022 at 23:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .