How to print error and exit if command fails?

Guys any tips on printing a certain error message to stderr and exiting should a command fail within a ksh script? I'm trying to null some output files.

Touch isn't suitable as i need to null them.
print "" > file isn't suitable as i need to check elsehere for if they are 0bytes or not.

I've tried these below examples and none work correctly. I don't want to have to put a check after each command as :-

if [[ $? -ne 0 ]];then
   print "error blah blah" >&2
   exit 2
fi

Below tests don't work correctly. I'm guessing its spawning something.

OUTFILE=/tmp/out

# Null outfiles. Security already checked

> ${OUTFILE} || print "ERROR: blah blah \n" >&2 ; exit 2   #doesnt work

> ${OUTFILE} || (print "ERROR: blah blah \n" >&2 ; exit 2 )  #doesn't work

> ${OUTFILE} || (print "ERROR: blah blah \n" >&2 && exit 2) #doesnt work

if [[ -n "$(> ${OUTFILE} 2>&1)" ]];then
     print "ERROR: blah blah \n" >&2
     exit 2
fi    # doesnt work

Any ideas or alternatives?

Specifically about reporting and exiting, this is a slightly more condensed idiom:

test $condition || { print "Crap blew up; exiting"; exit 2; }

You could also directly test for the result of your command:

command || { print "Crap blew up; exiting"; exit 2; }

I enjoy reading that out loud to myself as "either you do this or DIE!", as if threathening the script.

Thanks dude thats worked like a charm.

Seems i was almost there but didn't use the correct { }

Could you explain the difference between { } and ( ) in the command grouping? Also i notied the ; at the end before } is vitally important otherwise the next command doesn't work.

e.g

This works and exits if cant null but echos got to here if can.

> ${OUTFILE} || { print "ERROR: cannot null output file. Exiting\n" >&2; exit 2; }
> ${TMPFILE} || { print "ERROR: cannot null tmp file. Exiting\n" >&2; exit 2; }

echo "got to here"

This doesnt work and never gets to echo even if null is successful

> ${OUTFILE} || { print "ERROR: cannot null output file. Exiting\n" >&2; exit 2 }
> ${TMPFILE} || { print "ERROR: cannot null tmp file. Exiting\n" >&2; exit 2 }

echo "got to here"

() executes the statements in a new subshell, with separate state. {} executes stuff in the current shell.

Example:

(aVariable="hello"); echo $aVariable

this doesn't print "hello" because the variable was assigned inside a new shell, whose state was discarded when the () expression ended. Think of variable scoping in C; variables live and die inside the block where they're declared.

{aVariable="hello"; }; echo $aVariable

this prints "hello" because the variable was assigned in the same shell as the next statement.

It's the same difference as:

sh myScript.sh

and

source myScript.sh

Also, yes, you need a semicolon to end the last statement inside {}; that's how the shell's grammar is defined.
Kind of how you can either do this:

if $condition; then $statements; fi

or this, using newlines instead of semicolons to separate the syntax parts:

if $condition
then
    $statements
fi

According to the bash man page, it's different from () because { and } are reserved words instead of metacharacters, which means they don't automatically cause word breaks. Presumably the same applies in the rest of the shells.

Dude thats real great and an informative reply. Thanks a lot. Its certainly giving me a better understanding of the shell rather than just trying things until they work :slight_smile:

Don't mention it; I love yapping about bash.
Its man page is long and daunting, but flick through it every once in a while; you're bound to learn great tidbits every time.
The parts about history and readline are particularly cool, and they're handy and fun to use.