why error code 1 returned by loading .bash_profile in Mac

Solution 1:

Note that what happens when using return outside a function without having sourced the script (e.g. returning 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 returnwithout 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; }

Solution 2:

I have figured the following out by trial and error. Maybe a BASH guru can explain some more.

  1. .bashrc contents:

    test -f $HOME/existent_file || return 4
    

    After opening a new terminal:

    $ echo $?
    0
    
  2. .bashrc contents:

    test -f $HOME/non_existent_file || return 4
    

    After opening a new terminal:

    $ echo $?
    1
    
  3. .bashrc contents:

    function foo () { 
        return 4 
    }
    foo;
    

    After opening a new terminal:

    $ echo $?
    4
    
  4. .bashrc contents:

    return 4
    

    After opening a new terminal:

    $ echo $?
    0
    
  5. With the same .bashrc as above:

    $ source ~/.bashrc
    $ echo $?
    4
    
  6. These commands run directly from a terminal:

    $ test -f $HOME/existent_file  || return 4
    $ echo $?
    0
    $ test -f $HOME/non_existent_file  || return 4
    bash: return: can only `return' from a function or sourced script
    $ echo $?
    1
    

So, return only works from functions and sourced files. I don't know how a user's ~/.bashrc is read but apparently it is not sourced.