In Advanced Bash-Scripting Guide, in example 27-4, 7-th line from the bottom, I've read this:

A function runs as a sub-process.

I did a test in Bash, and it seems that the above statement is wrong.

Searches on this site, Bash Man, and my search engine don't bring any light.

Do you have the answer and would like to explain?

  • 12
    As noted, that guide is misleading in the extreme. I recommend the Wooledge Bash Guide instead. – Wildcard Aug 24 '16 at 1:39
  • An important fact is that "Bash" avoids to create subshells. They are expensive, has your own environment, and those affect performance of the script as well the way how the code flows (many times, inconveniently, in order to deal with their particularities). The actual state of Bash is a product of a evolution, a code evolution. I mean, the first version of Bash uses more subshells*** than the actual one. This kind of inconsistency seems to be reasonable. ***if you want a proof, I can't give you. I've derived it from webpages, comments... I've read that statement somewhere sometime ago. – Daniel Bandeira Jul 23 at 15:06

The Advanced Bash-Scripting Guide is not always reliable and its example scripts contain out-dated practices such as using the effectively deprecated backticks for command substitution, i.e., `command` rather than $(command).

In this particular case, it’s blatantly incorrect.

The section on Shell Functions in the (canonical) Bash manual definitively states that

Shell functions are executed in the current shell context; no new process is created to interpret them.

| improve this answer | |
  • 11
    "Advanced Bash-Scripting Guide is generally unreliable" Very true. – John1024 Aug 23 '16 at 23:31
  • 1
    Can you give references to support your first sentence? – Will Vousden Aug 24 '16 at 10:25
  • 6
    @WillVousden what would a reference look like here? A bunch of examples of the guide's technical shortfalls? A document where experts in the bash community have previously noted that it is unreliable? Would it help if a stackoverflow member with a gold badge in bash just agreed in a comment? :p – kojiro Aug 24 '16 at 11:13
  • 3
    @WillVousden I don't think what you want exists in a reliable form itself. Mendel Cooper has updated and fixed issues with the guide in the past, but there is no public bug tracker or list of errata. (Perhaps that is the most damning statement I can make.) So when we find a flaw (perceived or real) all we can do is email the author and hope for the best. – kojiro Aug 24 '16 at 11:46
  • 3
    @WillVousden, ...if you want a history of how long the consensus in the freenode #bash channel has been that the ABS should be avoided, see wooledge.org/~greybot/meta/abs -- the second field in each line is the timestamp, and the first is the username; I'm going to hope that assertion that the usernames in question are very well-respected individuals suffices. – Charles Duffy Aug 24 '16 at 17:57

Curly brace functions will run within the calling shell process, unless they need their own subshell which is:

  • when you run them in the background with &
  • when you run them as a link in a pipeline

Redirections or extra env. variables won't force a new subshell:

    echo hello world from $BASHPID
    echo var=$var
var=42 hw >&2
echo $BASHPID  #unexports var=42 and restores stdout here

If you define the function with parentheses instead of curlies:

  echo hello world from $BASHPID

it will always run in a new process.

Command substitution $() also always creates processes in bash (but not in ksh if you run builtins inside it).

| improve this answer | |
  • I didn't know f() (...) is allowed. Are there any other definitions apart from {...} and (...)? In Bash, I'm not into others yet. – user147505 Aug 23 '16 at 23:43
  • 1
    @tomas You can use the function hw { echo hello world; } syntax (no need for () if you type out function and you can specify redirections right after the final } or ) as in hw(){ echo error; } >&2. That's about it. – PSkocik Aug 23 '16 at 23:54
  • 2
    This is the answer I immediately thought about, and it is absolutely correct. It should be voted as the correct answer. f()(...) always execute an own shell, whilst f(){...} does not. – rexkogitans Aug 24 '16 at 8:22
  • 11
    NB bash functions accept any compound command, so foo() [[ x = x ]] is a valid function definition, too. However, if you look at the function with type foo you'll see that this is still syntactic sugar for foo() { [[ x = x ]]; }. The same is true of subshell functions: bar() ( : ) becomes bar() { ( : ); }. – kojiro Aug 24 '16 at 11:54
  • 1
    @kojiro nice +1. didn't know that – PSkocik Aug 24 '16 at 11:58

The command in question from that example looks like:

echo ${arrayZ[@]/%e/$(replacement)}

The example later states:

#    $( ... ) is command substitution.
#    A function runs as a sub-process.

Being charitable to ABS Guide, what they apparently meant to write is that the function runs inside a command substitution and the command inside a command substitution runs in a subshell.

| improve this answer | |
  • That's very misleading. Thanks for your interpretation. – user147505 Aug 23 '16 at 23:38
  • 5
    @tomas "very misleading." Yes, very. In contrast to the ABS Guide, Greg's Wiki is an excellent source of advanced bash information. – John1024 Aug 23 '16 at 23:44
  • 1
    Cheers. What's your opinion about this one: wiki.bash-hackers.org/start ? – user147505 Aug 23 '16 at 23:47
  • @tomas I have no first hand knowledge of that one. – John1024 Aug 23 '16 at 23:54
  • 2
    @tomas, ...my own opinion as to the bash-hackers wiki is that it's an excellent source. I haven't been through it as comprehensively as I have the Wooledge wiki, but it tends to be accurate and precisely written. – Charles Duffy Aug 24 '16 at 17:59

Your Answer

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