&& and || operators

Hello all,

i am curious how we can implement the ternary operator with multiple commands in else part. in my case, only the first command in the "else" part is reachable and the rest is ignored.

[[ `$adb_path devices|wc -l` -gt 2 ]] && echo "there's a device connected" || (echo "please connect a device" && exit -1) 

[[ `$adb_path devices|wc -l` -gt 2 ]] && echo "there's a device connected" || (echo "please connect a device";exit -1) 

in both the cases, the

exit

is not reachable always and the code continues without exiting.

please help me how to achieve this with this syntax. It can be easily rewritten using if-else construct. But, I would like to know how we can accomplish this using this syntax.

Thanks

The && and || operators are not a replacement for a proper if - else - fi block".

While one can use subshells, as you did, to do additional tasks if a false has returned, being a subshell, you cannot exit from there, as it just exits the subshell, not the script.

echo main shell pid: $$
false || (echo "subshell pid: $$" ; exit 1 )
exit 0

Now try:

function myText() { # STRING
# Prints the STRING 
# then exits
	local pid="${1:-$$}"
	echo "Subshell pid: $pid"
	# to end the script, use 'return 0|1' to return from function to script
	exit 1 
}

echo "main shell pid: $$"
false  || myText "$$"

Check if of the if blocks exit status, by executing:

echo $?

After you ran the script.

hth

EDIT:
Simply said, the && and || operators are only good for SIMPLE checks, not for complex checking.
MAinly because one cannot use multiple instances of || , if ANY previous condition fails, it'll go to the first || , and be done after.

1 Like

As sea said, your exit commands are exiting the subshell in which they're located; not the parent shell... But, you can reverse the condition and use multiple && operators with a single || operator. Try:

[[ $($adb_path devices|wc -l) -le 2 ]] && echo "please connect a device" && exit -1 || echo "there's a device connected"

However, just because you CAN do it this way doesn't mean that something more like:

if [[ $($adb_path devices|wc -l) -le 2 ]]
then	echo 'please connect a device'
	exit -1
fi
echo "there's a device connected"

wouldn't be better. This form is easier to read for most code readers and should run as fast or a tiny bit faster than the single line version.

Despite what sea said, a long command line can have more than one meaningful || operator if conditional code follows the first || . For example:

x=$((number % 3))
[[ x -eq 0 ]] && echo 0 || [[ x -eq 1 ]] && echo 1 || echo 2
2 Likes

To add: you can simply replace the subshell construct with code grouping

[[ $($adb_path devices|wc -l) -gt 2 ]] && echo "there's a device connected" || { echo "please connect a device";exit -1;}

Note the space after the first curly brace and the semicolon before the second one..

1 Like

Awesome, Worked like a charm. Thanks a lot.

NB if the echo "there's a device connected" is run then it is evaluated and must give a true (exit 0) status, otherwise the || part would run, too.

Well, a simple echo can hardly fail. But an if-then-else is cleaner.