Bash – Determine if Function Invoked via Command Substitution

bashcommand-substitutionsubshell

foo() {
  if [[ something ]]; then
    echo "The foo function was called directly."
  else
    echo "The foo function was invoked via command substitution."
  fi
}

Call foo directly:

foo

The foo function was called directly.

Call foo via command substitution:

a=$(foo) || exit 1
echo "${a}"

The foo function was invoked via command substitution

Is there any way to accomplish this?

Best Answer

I believe that one test that you could use is

if [[ $BASHPID -eq $$ ]]; then
    echo was called directly
else
    echo was called in a subshell
fi

The special value $$ will be the process ID of the shell executing the script. This would not change in subshells (of which a command substitution is one).

The special value $BASHPID will be the process ID of the shell executing the current code. This value would change inside a subshell.

Therefore, if they are different, the function is called in a subshell. You can't, as far as I know, know if this subshell is a command substitution or some other subshell.

You could also use

if [[ $BASH_SUBSHELL -eq 0 ]]; then
    echo was called directly
else
    echo was called in a subshell
fi

for the same effect in the code shown.

The BASH_SUBSHELL variable is incremented from zero for each additional level of nested subshells.