Let's see what the Bash manual says (3.7.3 Command Execution Environment)
The shell has an execution environment, which consists of the
following:
- shell parameters that are set by variable assignment or with set or inherited from the shell’s parent in the environment
- shell functions defined during execution or inherited from the shell’s parent in the environment
Command substitution, commands grouped with parentheses, and
asynchronous commands are invoked in a subshell environment that is
a duplicate of the shell environment [...]
Changes made to the subshell environment cannot affect the shell’s execution environment.
In 3.2.2 Pipelines, it's also said
Each command in a pipeline is executed in its own subshell
(Of course that only applies to multi-command pipelines)
So, the parts of a pipeline, as well as other subshells, get copies of all the shell variables, but any changes to them are not visible to the outside shell.
With other commands, you still need to export
:
When a simple command other than a builtin or shell function is to be
executed, it is invoked in a separate execution environment that
consists of the following.
- shell variables and functions marked for export, along with variables exported for the command, passed in the environment
Food for thought: what does this print?
bash -c 'f() { echo "$a $b"; }; a=1; b=1; (b=2; f); f'
while
structures, which is what that other Q is really about – ilkkachu Dec 13 '17 at 21:56export
command. – MiniMax Dec 13 '17 at 22:46ls -ltr
andwhile
runs each in the own subshell. Thus, they see only environment variables. – MiniMax Dec 13 '17 at 23:00while
loop gets a copy of the local (non-exported)var
variable, which is defined before the pipeline. Similar thing would happen if the left hand side of the pipe was something likeif true; then echo "$var"; var=quick; echo "The $var brown fox"; fi
. – G-Man Says 'Reinstate Monica' Dec 13 '17 at 23:38true | sed '' <<< $var
. Thesed
is not builtin command, but it also prints the value of the$var
. How it knows this value in the subshell? I think, that the expansion occurs in the parent shell and thesed
get the value of the$var
. I have elaborated this thought in the answer. – MiniMax Dec 13 '17 at 23:52