tags:

views:

77

answers:

4

I am a noob in shell-scripting. I want to print a message and exit my script if a command fails. I've tried :

my_command && (echo 'my_command failed; exit)

but it does not work. It keeps executing the instructions following this line in the script. I'm using Ubuntu and bash.

Thanks all.

A: 

Hello! Provided my_command is canonically designed, ie returns 0 when succeeds, then && is exactly the opposite of what you want. You want ||.

Also note that ( does not seem right to me in bash, but I cannot try from where I am. Tell me.

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}
Benoit
IIRC, you need semicolons after each of the lines inside {}
Alex Howansky
Thank you for pointing this!
Benoit
@Alex: not if they're on separate line.
Dennis Williamson
+6  A: 

Try:

my_command || { echo 'my_command failed' ; exit 1; }

Four changes:

  • Change && to ||
  • Use { } in place of ( )
  • Introduce ; after exit and
  • spaces after { and before }

Since you want to print the message and exit only when the command fails ( exits with non-zero value) you need a || not an &&.

cmd1 && cmd2

will run cmd2 when cmd1 succeeds(exit value 0). Where as

cmd1 || cmd2

will run cmd2 when cmd1 fails(exit value non-zero).

Using ( ) makes the command inside them run in a sub-shell and calling a exit from there causes you to exit the sub-shell and not your original shell, hence execution continues in your original shell.

To overcome this use { }

The last two changes are required by bash.

codaddict
A: 

Note also, each command's exit status is stored in the shell variable $?, which you can check immediately after running the command. A non-zero status indicates failure:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi
Alex Howansky
This can just be replaced by if my_command, there is no need to use the test command here.
Bart Sas
+1 because I think you oughtn't be punished for listing this alternative - it should be on the table - though it's kinda ugly and in my experience too easy to run another command in between without noticing the nature of the test (maybe I'm just stupid).
Tony
+2  A: 

The other answers have covered the direct question well, but you may also be interested in using set -e. With that, any command that fails (outside of specific contexts like if tests) will cause the script to abort. For certain scripts, it's very useful.

Daenyth