Is there such a feature or can it be emulated reasonably easily? I want the same behavior except it should return where set -e would have caused a call to exit.

3 Answers 3


Sub shell might be useful.

func() {(set -e
        echo a
        ehco b
        echo c


This script produces:

script.sh: line 3: ehco: command not found
script.sh: line 3: ehco: command not found
script.sh: line 3: ehco: command not found

Alternatively you might be interested in this try/catch implemetation in bash.

  • 5
    No need for the braces in this case: func () ( … ) is equivalent. Note that since the function is executed in a subshell, its variable assignments, redirections, etc. won't affect the caller. Jun 6, 2015 at 22:47
  • 2
    This fails to early-out if you run func && foo, if func then ... fi or similar constructs which depend on the exit status of func. See explanation. Apr 6, 2016 at 15:20

You can set the ERR trap, which is executed whenever a command returns a nonzero status.

In bash, it's a bit fiddly because traps are not local to functions. By default, traps are not inherited by subshells or subfunctions; call set -E to change this. Here's some demo code.


subroutine () {
  echo "Subroutine continued after status $?"

trapper () {
  local i ret
  trap 'ret=$?
        echo "Command $BASH_COMMAND returned status $ret"
        for ((i=0; i<$((${#FUNCNAME[@]}-1)); i++)) do
          echo "  from ${FUNCNAME[$i]} at ${BASH_SOURCE[$((i+1))]} line ${BASH_LINENO[$((i+1))]}"
        return $ret' ERR
  trap 'ret=$?; trap - ERR RETURN; return $ret' RETURN
  echo ok
  echo "By default, the ERR trap is not inherited"
  echo "You won't see this"

main () {
  echo "trapper returned status $?"
  echo "still there"


In zsh, you can define the TRAPZERR function instead of setting a trap for ERR (for compatibility) or ZERR (on systems with a signal called SIGERR — I don't know of any). But if all you want to do is return immediately (and not e.g. print an error message), it's simpler: just set the err_return option. Options are global by default; set the local_options option to make them local to the calling function (if the local_options option is set when a function returns, the options from the time the function was called are restored). Traps are also global by default. Options and traps are inherited in function calls.

myfunction () {
  setopt local_options err_return
  echo not executed
  • It does not look like the zsh solution has the behavior of set -o pipefail, just set -e. Any way to fix this? Aug 1, 2017 at 16:09
  • Oh, silly me assuming the online docs would be up to date. Recent versions of zsh have a setopt pipe_fail which works just fine. Aug 1, 2017 at 16:19
  • @RadonRosborough pipefail was outside the scope of the question. In bash, ksh and zsh you can do set -o pipefail (note that this isn't local to the function, except in zsh if you call setopt local_options in the function). This is not new and the online documentation is up-to-date, but not very easy to read. Aug 1, 2017 at 16:37
  • You're right that the official manual at zsh.sourceforge.net/Doc/Release/Options.html is perfectly well up to date. I was looking at linux.die.net/man/1/zshoptions from Google, which I should have been more clear about. Aug 1, 2017 at 17:51

With ksh93, if you use ksh's own syntax for funtion definition (function f {...;}), then options and traps have a local scope. So there, you can do:

function f {
  trap 'return 99' ERR
  set -e
  echo foo
  echo never output
echo "f exited with status $?"

Which gives:

f exited with status 99

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.