26

What I want to do using bash:

> if true; then echo y; else echo n; fi
y
> if false; then echo y; else echo n; fi
n
> if false || true; then echo y; else echo n; fi
y

Now trying with fish:

> if true; echo y; else; echo n; end
y
> if false; echo y; else; echo n; end
n

# Here 'or true' are just two arguments for false
> if false or true; echo y; else; echo n; end 
n

# Here 'or true;' is a command inside the if
> if false; or true; echo y; else; echo n; end 
n

# Can't use command substitution instead of a command
> if (false; or true); echo y; else; echo n; end
fish: Illegal command name “(false; or true)”

How can I have two conditions in an if?

Cœur
  • 37,241
  • 25
  • 195
  • 267
michelpm
  • 1,795
  • 2
  • 18
  • 31

4 Answers4

28

Two other approaches:

Approach one:

if begin false; or true; end
  echo y
else
  echo n
end

Approach two:

false; or true
and echo y
or echo n
terje
  • 4,164
  • 2
  • 28
  • 28
  • 1
    The approach one is probably what I was looking for, but approach two is very cool, but too much obscure. – michelpm Jul 27 '13 at 22:15
  • Agreed. I can't figure out why/how approach two actually works. Anyone care to explain? – clozach Sep 28 '17 at 17:48
  • It is quite simple: If either condition1 or condition2 is truthy it will continue, meaning it will enter the and statement and evaluate that together. Since the result from and is truthy it doesn't need to run the last or statement. However if both condition1 and condition2 is negative the and statement cancels early, no need to evaluate second part. The result from that statement becomes false and therefore the last or statement will run. – terje Nov 16 '17 at 23:45
  • 1
    For simple conditions on does not need `begin ... end`; here, `if false; or true` will work just fine. – Raphael Jan 06 '19 at 17:08
  • 1
    @clozach It's just acting on last command status value state, and you are either choosing a larger block format in the grammar, potentially for multiple commands or readability, or a smaller format that is just expecting a single statement, but you could also manually expand into a larger block with `begin; ...; end`. At that point you're just choosing convention. – Pysis Apr 24 '19 at 18:48
2

This way works, but it is an ugly hack:

> if test (true; and echo y); echo y; else; echo n; end 
y
> if test (false; and echo y); echo y; else; echo n; end 
n
> if test (false; or true; and echo y); echo y; else; echo n; end 
y

I sincerely hope for better answers.

michelpm
  • 1,795
  • 2
  • 18
  • 31
1

Since fish 2.3b1, one can directly chain commands in the if condition with and/or. The begin ... end is not necessary anymore. The official docs were updated in May 2016.

So now this works as expected:

> if false; or true; echo y; else; echo n; end
y
Aurelio Jargas
  • 370
  • 3
  • 5
0

For anyone looking for testing expressions: You can do something like the following (if $i is lower than $m or greater than $n):

if [ $i -lt $m ] || [ $i -gt $n ]
    echo "Voila!"
end
MAChitgarha
  • 3,728
  • 2
  • 33
  • 40