How to define the "die" shell function?

Note: this is not a duplicate. In bash, is there an equivalent to die "error msg" , as shown at the end of this post.

Consider the shell function

foo () { echo "testing..." 1>&2 return 1 echo "should never reach this point" 1>&2 } 

The following is the expected behavior of foo :

 % foo || echo $? testing... 1 

I would like to encapsulate the functionality shown in the first two lines of foo in the die function, so that the definition of foo can be reduced to

 foo () { die 1 "testing..." echo "should never reach this point" 1>&2 } 

... while maintaining its original behavior.

My interest is primarily zsh , but it will also be interesting for answers suitable for bash scripts and / or /bin/sh if they are different.


By the way, this will not work:

 die () { local exit_code=$1 shift echo "$*" 1>&2 exit $exit_code } 

If the version of foo that used this die was selected from the command line, the result would be to kill one current shell (at least this is the result I get when I try something like this). This is why this question is not a duplicate. In bash, is there an equivalent to die "error msg" . Anyway, the answer to this other question will not satisfy my requirements here.

+4
source share
2 answers

Strictly speaking, I do not think that what you want is possible. You cannot return from a function simply by calling another function. This may be close to what you want:

 die () { echo "${*:2}" 1>&2 return $1 } foo () ( # Parentheses, not braces, to enclose the body set -e die 1 "testing..." echo "Shouldn't reach here" 1>&2 ) 

When die returns with status 1, set -e causes the current shell to exit. However, the body of foo launched a new subshell, so what exits returns control to a shell called foo . However, there are two egregious problems:

  • set -e; die... set -e; die... no shorter than echo...; return 1 echo...; return 1
  • Creating a subshell foo body will prevent all variables set in this function from being visible to the caller.
+1
source

As in zsh 4.3.4, you can use the throw / catch syntax. I find it much less problematic than the old school "set -e" or exit for error handling. Just make sure you run "autoload -U throw catch" to access them. See man zshcontrib for more information.

0
source

All Articles