When sourcing a script with either source
or .
, the contents of the script is executed in the current shell's environment. Any functions defined in the sourced script will be available in the current shell after sourcing, as well as any shell variables (without the need for exporting). This is the purpose of sourcing a script.
This is how a /etc/profile
or /etc/bash.bashrc
file is able to set up a basic environment for a interactive/login shell, for example.
Moreover, some commands are executed in a subshell environment that is a duplicate of the shell environment. In such an environment, shell variables and functions are available. See also the POSIX standard about Shell Execution Environment (my emphasis):
A subshell environment shall be created as a duplicate of the shell environment, except that signal traps that are not being ignored shall be set to the default action. Changes made to the subshell environment shall not affect the shell environment. Command substitution, commands that are grouped with parentheses, and asynchronous lists shall be executed in a subshell environment. Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
Note that a subshell is different from a child process.
Exporting a variable is only needed to create an environment variable. Environment variables are inherited by any child process.
Also note that having a directory called ~/.bash_profile
is a bit confusing, as a bash
shell will try to source the regular file ~/.bash_profile
when starting a login shell. I suggest that you rename your ~/.bash_profile
directory into something like ~/.shell
or ~/.shell_startup
if you want to move your shell initialization files elsewhere. These file would still have to be called from ~/.bash_profile
and ~/.bashrc
if you wish them to be sourced automatically.
bash -c 'foo() { echo bar; }; (foo)'
andbash -c 'function foo { echo bar; }; (foo)'
work fine, and the linked question's answers do not mention any difference related to export behaviour. (And neitherbash -c 'function foo { echo bar; }; bash -c foo'
norbash -c 'foo() { echo bar; }; bash -c foo'
work: both fail withfoo
not being found.) – muru Jun 25 '18 at 05:04