Note that what happens when using return
outside a function without having source
d the script (e.g. return
ing from .bash_profile
) is undocumented in man bash
.
The difference is in how the return code of a script or function is recorded internally in bash
. If you return
a value, that value is assigned the return code of the calling code, e.g. the function call you return from, or the source
command. As there is no such caller when returning from .bash_profile
during shell initialization, that value is simply discarded. What you're accessing as $?
is the return code of the preceding statement.
Using Apple's bash-86.1 as reference:
If you source
a script, its contents are parsed and executed, until a return
statement is encountered. Its return value is recorded separately, and it's the responsibility of the caller (execute_command_internal
in bash-3.2/execute_cmd.c
) to assign its value to the variable holding the last exit code: last_command_exit_value
.
If it's called as a startup script, it is loaded via a call to maybe_execute_file
in the run_startup_files
function in bash/shell.c
. It's not regular command execution: While the contents of the file are executed properly, including the final return
, nobody cares about the actual value you're returning. It is simply discarded.
So, what behavior are you seeing here? Essentially the same as if you'd called return
without argument: Like return
simply returned the return code of the command preceding it, which, in your case, is the failed test.
How to get the desired behavior? Since you can't exit
from .bash_profile
without quitting the shell, you need to make sure the command immediately preceding it produces the desired return code, in this case:
test -f $HOME/.debug && export profile_bash_profile='.bash_profile' || { true; return; }
Best Answer
Use a function instead: