4
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?

7

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.

1
  • 1
    You could have answered my original question with a simple "No," and you would have been technically correct. Instead, you answered the question I should have asked in the first place. You, sir, are a rock star. Thank you very much. Jun 24 '20 at 14:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.