ChatGPT解决这个技术问题 Extra ChatGPT

Negate if condition in bash script

I'm new to bash and I'm stuck at trying to negate the following command:

wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
        echo "Sorry you are Offline"
        exit 1

This if condition returns true if I'm connected to the internet. I want it to happen the other way around but putting ! anywhere doesn't seem to work.

Where did you put it? if ! [[ ... works
you can also use it this way: wget your_xxxx_params || ( echo "oh oh" && exit 1)
> calling a subshell just to output an error

C
Cyrus

You can choose:

if [[ $? -ne 0 ]]; then       # -ne: not equal

if ! [[ $? -eq 0 ]]; then     # -eq: equal

if [[ ! $? -eq 0 ]]; then

! inverts the return of the following expression, respectively.


are the double brackets necessary? why is that?
@AlexanderMills: There are several ways to do this. With double or single brackets or with test command: if test $? -ne 0; then
This answer is unnecessary verbose. if expects a statement that is either 0 or 1, so you can use the command itself and invert it: if ! wget ...; then ...; fi
Z
Zombo

Better

if ! wget -q --spider --tries=10 --timeout=20 google.com
then
  echo 'Sorry you are Offline'
  exit 1
fi

Important: keep a space between the ! and the following command otherwise you will be doing a history expansion. unix.stackexchange.com/questions/3747/…
Steven why do you have only 1 reputation?
Looks like Steven has been banned - if you check out his profile it says he's suspended until autumn 2022 😳
C
Cole Tierney

If you're feeling lazy, here's a terse method of handling conditions using || (or) and && (and) after the operation:

wget -q --tries=10 --timeout=20 --spider http://google.com || \
{ echo "Sorry you are Offline" && exit 1; }

In real-life scripts you should change the && after the echo command to a ;. The reason for this is that if the output is being redirected to a file on a full disk, the echo will return failure and the exit will never fire. This is probably not the behaviour you want.
or you can use set -e and failing echo will exit the script anyway
B
Benjamin W.

Since you're comparing numbers, you can use an arithmetic expression, which allows for simpler handling of parameters and comparison:

wget -q --tries=10 --timeout=20 --spider http://google.com
if (( $? != 0 )); then
    echo "Sorry you are Offline"
    exit 1
fi

Notice how instead of -ne, you can just use !=. In an arithmetic context, we don't even have to prepend $ to parameters, i.e.,

var_a=1
var_b=2
(( var_a < var_b )) && echo "a is smaller"

works perfectly fine. This doesn't appply to the $? special parameter, though.

Further, since (( ... )) evaluates non-zero values to true, i.e., has a return status of 0 for non-zero values and a return status of 1 otherwise, we could shorten to

if (( $? )); then

but this might confuse more people than the keystrokes saved are worth.

The (( ... )) construct is available in Bash, but not required by the POSIX shell specification (mentioned as possible extension, though).

This all being said, it's better to avoid $? altogether in my opinion, as in Cole's answer and Steven's answer.


@DavidC.Rankin Oh, I didn't find that! So it's mentioned as an extension, but not required. I'll amend.
Yes, that one always got me too. It sure makes life easier in shell though :)
V
Victor Schröder

You can use unequal comparison -ne instead of -eq:

wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -ne 0 ]]; then
    echo "Sorry you are Offline"
    exit 1
fi