Edit:
My comment below regarding sed 's@^@ @' <(f1)
is incorrect
While $BASH_SUBSHELL
indicates that we are in the same level as the launch, the variables are lost in the main script.
based on Gordons answer I tested f1 > >(sed 's@^@ @')
instead and that seems to work correctly. Still, shouldn't BASH_SUBSHELL should be 1 and not 0 for the first form?
Consider this small test
#!/bin/bash
declare -i i=0
function f1()
{
let i++
echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}
f1
f1 | sed 's@^@ @'
echo "at end, i=$i"
with the following output:
In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
at end, i=1
(the purpose of the sed
is just to have a pipe to something, don't expect it to do anything because f1 outputs to stderr)
The function f1 logs the current BASH_SUBSHELL and the current value of i
I know why at the end of the script we get i=1
, its because the second invocation was in a subshell, and the value of i at subshell 1 was lost.
What I don't know is why the left side of the pipe was not executed in the current shell
Though I figured that I could avoid this with sed 's@^@ @' <(f1)
I would like to know why the left side is not at the same level as the main script
From the bash man page: "Each command in a pipeline is executed as a separate process (i.e., in a subshell)." I suppose it would be possible to execute one component of a pipeline in the current shell (i.e. the first, or the last, or maybe one in the middle), it doesn't play favorites like this: they all execute in subshells. If you modify your script like this:
#!/bin/bash
declare -i i=0
function f1()
{
let i++
echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}
f1
f1 | f1 | f1
echo "at end, i=$i"
it prints:
In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
In f1, SUBSHELL: 1, i=2
In f1, SUBSHELL: 1, i=2
at end, i=1
because all 3 invocations of f1 in the pipeline run in subshells.