7

Pretty new to shell scripting. I am trying to do the following:

#!/bin/bash

unzip myfile.zip

#do stuff if unzip successful

I know that I can just chain the commands together in with && but there is quite a chunk, it would not be terribly maintainable.

Mild Fuzz
  • 29,463
  • 31
  • 100
  • 148
  • 2
    possible duplicate of [Aborting a shell script if any command returns a non-zero value?](http://stackoverflow.com/questions/821396/aborting-a-shell-script-if-any-command-returns-a-non-zero-value) – Gilles 'SO- stop being evil' Jun 04 '13 at 13:45
  • 1
    No way, this isn't a dupe, and I'm surprised anyone thinks it is. That question is about *aborting* an entire script based on *any* unsuccessful statement, this one is about exiting if a *specific* statement is unsuccessful. – kojiro Jun 06 '13 at 13:52

4 Answers4

12

You can use the exit status of the command explicitly in the test:

if ! unzip myfile.zip &> /dev/null; then
    # handle error
fi
  • @MildFuzz `/dev/null` is the bit-bucket, you can redirect anything you like to it and it will get thrown away. 2>&1 tells it to direct stderr to the stdout. – Philip Kearns Jun 04 '13 at 17:34
11

You can use $?. It returns:
- 0 if the command was successfully executed.
- !0 if the command was unsuccessful.

So you can do

#!/bin/bash

unzip myfile.zip

if [ "$?" -eq 0 ]; then
    #do stuff on unzip successful
fi

Test

$ cat a
hello
$ echo $?
0
$ cat b
cat: b: No such file or directory
$ echo $?
1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 1
    This is mostly correct. Most processes return `0` on success and **non-zero** on failure. It won't necessarily be `1`. – Sean Bright Jun 04 '13 at 13:37
  • 1
    This works, but it's not entirely correct. `$?` contains the exit status of the most recently executed command. That depends on the command and, in the case of the `unzip` command there are 17 possible return values. The information about exit status is usually found in the man page for the command. –  Jun 04 '13 at 13:42
  • `[ $? ] && echo "error!"` will echo `error` even if `$?` is `0`. It tests whether the string is *empty*, not whether the string is *nonzero*. – Charles Duffy Apr 02 '19 at 14:30
  • @CharlesDuffy mm, true. Quite a lot of time since I wrote this, but I guess `[ "$?" -eq 0 ]` is the way to go? – fedorqui Apr 02 '19 at 14:45
  • `if unzip myfile.zip; then` would be even better, but yes, if you're going to do the comparison after-the-fact, your above comment is an improvement on what's in the answer now. – Charles Duffy Apr 02 '19 at 14:49
  • @CharlesDuffy yes, the `if unzip myfile; then` sounds best to me, only that it is already in the accepted answer and don't think it is fair to copy it :) Updated to remove the wrong approach – fedorqui Apr 02 '19 at 14:51
5

The variable $? contains the exit status of the previous command. A successful exit status for (most) commands is (usually) 0, so just check for that...

#!/bin/bash
unzip myfile.zip

if [ $? == 0 ]
then
    # Do something
fi
  • By definition, a command is successful if and only if it has an exit status of zero. – William Pursell Jun 04 '13 at 14:17
  • @WilliamPursell I'm sure *someone* has a definition which says a command is successful if and only if it has an exit status of 0, but that's wrong. It's impossible since "success" is subjective and isn't always boolean. An exit status of 0 indicates only that a condition has been met. For example `grep` returns 0 if it has found a pattern and 1 if it hasn't. The exit status of 1 indicates that it has executed successfully, but hasn't found the pattern. Add the `-q` option and it returns 0 even if there's an error. In contrast, `find` returns 0 even if it hasn't found its pattern. –  Jun 05 '13 at 14:32
  • Why would you do this rather than `if unzip myfile.zip; then : "Do something"; fi`? Decoupling through `$?` just adds potential for bugs -- add an `echo` between your `unzip` and your `if`, and suddenly `$?` reflects the exit status of the logging statement, not the unzip command. – Charles Duffy Apr 02 '19 at 14:31
4

If you want the shell to check the result of the executed commands and stop interpretation when something returns non-zero value you can add set -e which means Exit immediately if a command exits with a non-zero status. I'm using this often in scripts.

#!/bin/sh

set -e

# here goes the rest
Grzegorz Żur
  • 47,257
  • 14
  • 109
  • 105
  • 2
    You say `-e`, but you use `-x` in your example. Also, you could just put it in your shebang: `#!/bin/sh -e`. – kojiro Jun 04 '13 at 13:52