5

Say I have a script where I have exported a variable as seen below:

#!/bin/bash
foo(){
    eval export one=1
}
foo1(){
    eval export two=2
}
(foo)
foo1
echo "one=$one"
echo "two=$two"

However I got the following output:

root@centos1:~>/tmp/test.sh
one=
two=2 

What might be reason that I am unable to see value of $one and can see $two?

2 Answers2

7

Global variables live from the moment they're set up until the moment they're unset or the process ends. Global (nor local) variables are not inherited by unrelated child processes (if the child process is a fork (a subshell) then it gets a copy of everything -- exported or nonexported).

Global exported variables are like global variables, but they're also automatically inherited (as part of the process environment) by, even unrelated, child processes. (With exports, you can pass a variable such as CXXFLAGS to a process such as make, which most definitely isn't a subshell of your shell, and every process that that make spawns will also get that variable too.)

In your example () creates a subshell, which gets a copy of everything. The foo command modifies the subshell by adding an exported variable and then the subshell ends without ever utilizing the exported variable (no grandchild inheritted it). Now, no information implicitly travels from child processes to parent processes. What children do in their environment has no affect on their parents. That is the reason why your variable one is unset.


BTW, those evals are an unnecessary eval in this context.

Petr Skocik
  • 28,816
2

Enclosing a command between ( ) will result in the command being in a sub shell.

This can be useful if one is to pipe, or exit.

For example, the following commands

( date ; cmd1 ; cmd2 ) | grep ...

will result in concatenating the first 3 commands and giving output to grep.

You might consider { }, for which you should refer to the man page for bash (bash(1)); here is an excerpt:

(list)

    list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).  Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes.  The return status is the exit status of list.

{ list; }

    list is simply executed in the current shell environment.  list must be terminated with a newline or semicolon.  This is known as a group command.  The return status is the exit status of list.  Note that unlike the metacharacters ( and ), { and } are reserved words and must occur where a reserved word is permitted to be recognized.  Since they do not cause a word break, they must be separated from list by whitespace or another shell metacharacter.

See also What are the shell's control and redirection operators?

Archemar
  • 31,554