Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash one-line conditional fails when using set -e

Tags:

bash

I started using set -e in my bash scripts, and discovered that short form of conditional expression breaks the script execution.

For example the following line should check that $var is not empty:

[ -z "$var" ] && die "result is empty"

But causes silent exit from script when $var has non-zero length.

I used this form of conditional expression in many places...

What should I do to make it run correctly? Rewrite everything with "if" construction (which would be ugly)? Or abandon "set -e"?

Edit: Everybody is asking for the code. Here is full [non]working example:

#!/bin/bash
set -e

function check_me()
{
    ws="smth"
    [ -z "$ws" ] && echo " fail" && exit 1
}

echo "checking wrong thing"
check_me
echo "check finished"

I'd expect it to print both echoes before and after function call. But it silently fails in the check_me function. Output is:

checking wrong thing
like image 828
LiMar Avatar asked May 01 '26 19:05

LiMar


2 Answers

Use

[ -n "$var" ] || die "result is empty"

This way, the return value of the entire statement is true if $var is non-empty, so the ERR trap is not triggered.

like image 111
l0b0 Avatar answered May 03 '26 17:05

l0b0


I'm afraid you will have to rewrite everything so no false statements occur.

The definition of set -e is clear:

-e Exit immediately if a simple command (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a && or || list, or if the command's return value is being inverted via !. A trap on ERR, if set, is executed before the shell exits.

You are using the "optimization" system of Bash: because a false statement will cause an AND (&&) statement never to be true, bash knows it doesn't have to execute the second part of the line. However, this is a clever "abuse" of the system, not intended behaviour and therefore incompatible with set -e. You will have to rewrite everything so it is using proper ifs.

like image 21
Peter Avatar answered May 03 '26 19:05

Peter