When I read this answer about $? another question comes to mind.

Is there any best practice for how to use $? in bash?

Let's have a example:

We have a linear script and I we would like to know that all the command was executed ok. Do you think it is ok to call a small function (let's call it "did_it_work"), to check the error code and break if it's not.


function did_it_work {
    if [ "$code" -ne "0" ]
        echo "Error failure: code $code "
        exit 1


mkdir -p $dir
did_it_work $? 

cd $dir
did_it_work $? 

did_it_work $? 

This approach of course means that I have to manually solve the problem if there is any and rerun the script.

Do you think this is a good idea or is there some other best practice to do this?


3 Answers 3


One common way is:

die() {
    IFS=' ' # make sure "$*" is joined with spaces

    # output the arguments if any on stderr:
    [ "$#" -eq 0 ] || printf '%s\n' "$*" 1>&2
    exit 1

then you use it like this:

mkdir -p some/path || die "mkdir failed with status $?"

Or if you want it to include the exit status, you could change it to:

die() {
    IFS=' '
    printf '%s\n' "FATAL ERROR: $* (status $last_exit_status)" 1>&2
    exit 1

and then using it is a bit easier:

mkdir -p some/path || die "mkdir failed"

When it fails, mkdir will likely already have issued an error message, so that second one may be seen as redundant, and you could just do:

mkdir -p some/path || exit   # with the same (failing) exit status as mkdir's
mkdir -p some/path || exit 1 # with exit status 1 always

(or use the first variant of die above without argument)

Just in case you haven't seen command1 || command2 before, it runs command1, and if command1 fails, it runs command2.

So you can read it like "make the directory or die".

Your example would look like:

mkdir -p some/path || die "mkdir failed"
cd some/path || die "cd failed"
some_command || die "some_command failed"

Or you can align the dies further on the right so that the main code is more obvious.

mkdir -p some/path         || die "mkdir failed"
cd some/path               || die "cd failed"
some_command               || die "some_command failed"

Or on the following line when the command lines are long:

mkdir -p some/path ||
  die "mkdir failed"

cd some/path ||
  die "cd failed"

some_command ||
  die "some_command failed"

Also, if you are going to use the name some/path multiple times, store it in a variable so you don't have to keep typing it, and can easily change it if you need to. And when passing variable arguments to commands, make sure to use the -- option delimiter so that the argument is not taken as an option if it starts with -.

mkdir -p -- "$dir"         || die "Cannot make $dir"
cd -P -- "$dir"            || die "Cannot cd to $dir"
some_command               || die "Cannot run some_command"

You could rewrite your code like this:

function try {
    if [ $code -ne 0 ]
        echo "$1 did not work: exit status $code"
        exit 1

try mkdir -p some/path
try cd some/path
try run_some_command

If you don't actually need to log the error code, but just whether the command succeeded or not, you can shorten try() further like so:

function try {
    if ! "$@"
        echo "$1 did not work"
        exit 1
  • You can also use the code in this format. <pre>function try {
    – BillThor
    Mar 7, 2011 at 17:40
  • If you use this functionality inline and don't want to return from the true side you can replace return $? with the : builtin.
    – BillThor
    Mar 7, 2011 at 17:50

If you really want to exit on an error and are using Bash, then you should also consider set -e. From help set:

-e Exit immediately if a command exits with a non-zero status.

This of course doesn't give you the flexibility of a did_it_work() function, but it is an easy way to make sure your bash script stops on an error without adding lots of calls to your new function.

  • set -e is useful. There are some commands that return non-zero under normal circumstances (for instance, diff). When I'm using set -e in a script where I'm expecting a nonzero return, I do command || true. Mar 7, 2011 at 18:49
  • 2
    Furthermore, even if you use set -e, you can set an “exception handler” to catch all errors with trap did_it_work EXIT. Mar 8, 2011 at 18:41
  • 1
    This is part of POSIX, not a bash specific feature. Use it but be aware of some pitfalls mywiki.wooledge.org/BashFAQ/105
    – kmkaplan
    Feb 5, 2014 at 7:46
  • @ShawnJ.Goff I prefer to do command && true. Like that the return value is not changed.
    – kmkaplan
    Feb 5, 2014 at 7:49
  • @kmkaplan Your last comment doesn't make any sense to me. The purpose of command || true is to prevent set -e from exiting the script if command returns a non-zero exit code. It changes the exit code because we need to. The only thing command && true does is run true (return a zero exit code) if `command succeeded (returned a zero exit code) - it's a complete no-op.
    – tripleee
    Jun 18, 2019 at 4:32

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.