On Mon, Mar 30, 2020 at 08:39:08PM +0200, Johannes Schindelin wrote: > > So my perspective was the opposite of yours: "return" is the officially > > sanctioned way to exit early from a test snippet, and "exit" only > > happens to work because of the undocumented fact that lazy prereqs > > happen in a subshell. But it turns out neither was documented. :) > > Can a subshell inside a function cause a `return` from said function? I > don't think so, but let's put that to a test: > [...] > To me, the fact that that `return` does not return from the function, but > only exits the subshell, in my mind lends more credence to the idea that > `exit` is more appropriate in this context than `return`. Hmm, yeah, I was wrong about it actually returning from the function. Thanks for demonstrating. Returning from just the subshell in the case of lazy_prereq is OK for our purposes, since the exit value of the subshell is taken as the result of the prereq check (and in turn becomes the return value of that function anyway). But it does make more sympathetic to the idea that "exit" is appropriate here. Especially given the prodding below (which you can skip to the last paragraph if you're not interested in shell arcana): > For shiggles, I also added that `$?` because I really, _really_ wanted to > know whether my reading of GNU Bash's documentation was correct, and it > appears I was mistaken: apparently `return` used outside a function does > _not_ cause a non-zero exit code. I think the issue may be in the definition of "outside a function". If we really are at the top-level outside of a function, then return gives a non-zero exit but _doesn't_ return in bash: $ bash -c 'return 2; echo inside=$?'; echo outside=$? bash: line 0: return: can only `return' from a function or sourced script inside=1 outside=0 So even though we asked to return 2, it gave us a generic "1" return code and continued executing (and then outside=0 because the echo was successful). And that's true even in a subshell (not we moved "outside" into the bash process so we can see that it keeps going): $ bash -c '(return 2; echo inside=$?); echo outside=$?' bash: line 0: return: can only `return' from a function or sourced script inside=1 outside=0 But if we actually _are_ inside a function, even inside a subshell, then return "works", by stopping execution in the subshell and returning the value we asked (in your example we got "0" because you didn't specify a value for "return", so it just propagated the exit code of the earlier "echo"). $ bash -c 'f() { (return 2; echo inside=$?); echo outside=$?; }; f' outside=2 It's just a bit odd (to me) that it still runs the rest of the function. Dash behaves a bit more sensibly with an out-of-function return, just returning from the script: $ dash -c 'return 2; echo inside=$?'; echo outside=$? outside=2 and with a subshell, it returns only from that subshell: $ dash -c '(return 2; echo inside=$?); echo outside=$?' outside=2 So inside a subshell-in-a-function, it behaves exactly the same (returning from the subshell but not the function). I think the behavior of both shells is fine for our purposes. We _are_ in a function, so as long as we return from the subshell immediately we're happy. But given the oddities in how bash behaves, and the fact that POSIX says: If the shell is not currently executing a function or dot script, the results are unspecified. it may be better to stay away from the question entirely. -Peff