Answer first
- The init-script does nothing to do with the return value.
- The process substitution
<(...)
is the real cause.
Explanation
[Proof1] Now try this command below. It has no option --init-file
, but same output (with some trivial prints).
(exit 10)
bash <( echo "type blah; echo $?" )
[Proof2] Try following commands, and change the number in first one, you will find more different return value.
(exit 117)
bash --init-file <( echo "type blah; echo $?" )
[Proof3] What output do you see?
(exit 23)
cat <( echo "type blah; echo $?" )
I think you can understand Answer1 via the 3 proofs above. What about Answer2?
If you just type the simple command echo "type blah; echo $?"
to run it, what result do you expect? You expect it will print type blah; echo <num>
, of which the <num>
is the return value of the last command. Right? We all know the $?
will be replaced with a number, because we all know bash will perform parameter expansion on $?
.
It is same in process substitution <(...)
.
In Bash, commands which appear in a process substitution <(...)
will be invoked in a subshell. Subshell is also a shell(Bash). So for the command echo "type blah; echo $?"
, you will get the exactly same result in subshell as you run it straightforward in current shell, which means subshell will also perform parameter expansion on $?
, just like what a bash does.
So when you are running bash --init-file <(echo "type blah; echo $?")
, the content of the init-script file is actually type blah; echo <num>
rather than type blah; echo $?
.
Deeper
Although in process substitution <(echo "type blah; echo $?")
the $?
is expanded by subshell, its value is affected by current shell. The value of ?
in subshell is as same as the one in current shell.
See the Proof2, the first command is (exit 117)
, which makes the value of $?
in current shell be 117. But it is expanded to 117 in subshell too.
This is because the commands appearing in process substitution <(...)
are invoked in a subshell environment that is a duplicate of the current shell environment.
So this explains in your question you showed different return value if you put option -i
in the command. That is not the difference brought by option -i
. That is because before that command, you definitely execute another command which returns 2.
More words
In fact, there are three other forms working the same way as process substitution in bash.
- Command substitution
$(...)
or `...`
- Commands grouped with parentheses
(...)
- Builtin commands in pipeline
<builtin cmd> | ...
or ... | <builtin cmd>
or <builtin cmd> | <builtin cmd>