Bash: Return or exit?

From FVue
Jump to: navigation, search

Problem

I want a shell script e.g. error.sh, to change the current directory when invoked interactive. But the script might also be called from another script. For example, consider these execution scenarios:

Scenario 1, called directly from command line

Source'd because for example, I want the script to change the current working directory:

source ./error.sh

Scenario 2, called from another script

#!/bin/bash
if ! ./error.sh; then
    echo "Error occurred"
fi

The script can't use exit because this will kill the active process of scenario 1.
The script can't use return because you "can only `return' from a function or sourced script".

Solution

Don't use either return or exit directly, but indirectly return exit status of last command:

$(exit n)

Or even better, because you don't need a subshell:

true     # $(exit 0)
false    # $(exit 1)

This satisfies both source'd and exec'ed scripts.

Journal

20060429

Trying return:

#!/bin/bash
#--- error.sh ------
cd ~/proj
return 1

. error.sh   #  Does work in scenario 1.  But I always forget the . (source)
             #+  before the script and the path-to-the-script, so I want an
             #+ easier solution.

             #  Scenario 2 will also fail:
             #+ ./error.sh: line 4: return: can only `return' from a
             #+ function or sourced script
#!/bin/bash
if ! ./error.sh; then
    echo "Error occurred"
fi

Trying exit:

             #  This doesn work in scenario 1, but fails scenario 2:
             #  When this script is sourced, it'll exit the main process
#!/bin/bash
#--- error.sh ------
cd ~/proj
exit 1


Solution:

             #  The solution?  Don't specify either return or exit.
             #+ Instead make use of Bash feature to return status of last command.
#!/bin/bash
#--- error.sh ------
cd ~/proj
$(exit 1)
             #  Wrapping the script in a function eases me :-)
function error() {
    cd ~/error
    . error.sh
}
             # Combined with the function above, both scenarios are now satisfied:
error        # Scenario 1:  Changes current directory and returns error status.

             # Scenario 2:  Returns error status.
#!/bin/bash
if ! ./error.sh; then
    echo "Error occurred"
fi

Comments

blog comments powered by Disqus