This question is a sequel of sorts to my earlier question. The users on this site kindly helped me determine how to write a bash for loop that iterates over string values. For example, suppose that a loop control variable fname iterates over the strings "a.txt" "b.txt" "c.txt". I would like to echo "yes!" when fname has the value "a.txt" or "c.txt", and echo "no!" otherwise. I have tried the following bash shell script:


for fname in "a.txt" "b.txt" "c.txt"
  echo $fname
  if [ "$fname" = "a.txt" ] | [ "$fname" = "c.txt" ]; then
    echo "yes!"
    echo "no!"

I obtain the output:







Why does the if statement apparently yield true when fname has the value "a.txt"? Have I used | incorrectly?

  • 9
    In bash, 'or' operator is '||' (C style). Commented Sep 8, 2012 at 20:47
  • 8
    You can also use -o within the same [ ].
    – Thor
    Commented Sep 8, 2012 at 20:53
  • 11
    @Thor I'd prefer || and separate [ ] over -o for portability simply because [ is not guaranteed to support more than 4 arguments. Of course if the target language is bash, no one should be using [ anyways because bash's [[ is superior in many ways.
    – jw013
    Commented Sep 9, 2012 at 0:46
  • 3
    @jw013 Thanks. Does this mean that I should be using if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]] rather than if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]?
    – Andrew
    Commented Sep 9, 2012 at 17:14
  • 11
    @Andrew That is correct, if as you are declaring the shebang as bash, as you are already doing. One advantage of [[ is that it doesn't do word splitting (special case) so [[ $unquoted_var = string ]] is safe.
    – jw013
    Commented Sep 10, 2012 at 2:06

4 Answers 4


If you want to say OR use double pipe (||).

if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]

(The original OP code using | was simply piping the output of the left side to the right side, in the same way any ordinary pipe works.)

After many years of comments and misunderstanding, allow me to clarify.

To do OR you use ||.

Whether you use [ or [[ or test or (( all depends on what you need on a case by case basis. It's wrong to say that one of those is preferred in all cases. Sometimes [ is right and [[ is wrong. But that's not what the question was. OP asked why | didn't work. The answer is because it should be || instead.

  • 20
    Furthermore, || doesn't do a standard logic "OR" - it short-circuits, and the second command is run only if the first fails.
    – holdenweb
    Commented Dec 12, 2016 at 19:33
  • 43
    @holdenweb I'm pretty sure most modern optimized languages work the same way. No need to spend CPU cycles evaluating the second condition of OR if the first condition evaluates true.
    – bahamat
    Commented Dec 12, 2016 at 20:50
  • 16
    I thought bash liked == but after seeing this answer, I decided to look it up. Apparently, "it can be used but isn't standard". I thought I'd put this here for others if your curious: stackoverflow.com/a/2237103 Commented Sep 17, 2018 at 15:55
  • 9
    You can also use double bracket tests - if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]] (If you want or need to have the extra functionality associated with [[ ]]).
    – HankCa
    Commented Apr 24, 2019 at 5:45
  • 3
    @Massimo Since [ is the same thing as test, it's literally the same answer.
    – bahamat
    Commented Jun 3, 2020 at 18:43

The accepted answer is good but since you're using bash I'll add the bash solution:

if [[ "$fname" == "a.txt" || "$fname" == "c.txt" ]]; then

This is documented in the bash reference manual Conditional Constructs

expression1 && expression2

True if both expression1 and expression2 are true.

expression1 || expression2

True if either expression1 or expression2 is true.

The && and || operators do not evaluate expression2 if the value of expression1 is sufficient to determine the return value of the entire conditional expression.

  • 14
    +1 Agree this is the better answer (vs the "accepted" answer). Careful readers should note that the || (or &&) are inside the conditional, which in this case necessarily uses [[...]] and not [...] (i.e., it's not the shell's "or"/"and"). I'll only add that [[ ... ]] is not only more useful, supports more options (eg ||, &&, <, >) but also "safer" than older [ ...] ; the old -a and -o from the single-bracket syntax is supported, too, and as expected, operators "and" take precedence over "or". tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS
    – michael
    Commented May 19, 2020 at 23:30
  • 1
    I think @AnandShanbhag answer is better than this. Why spend neurons to bother about single or double brackets? C'mon, let do a favor to your readers: use test
    – Massimo
    Commented Jun 3, 2020 at 19:49
  • For the && operator is this true? "The && and || operators do not evaluate expression2 if the value of expression1 is sufficient to determine the return value of the entire conditional expression." I understand the || case, but does anyone know of an example with the && case where you wouldn't need to evaluate expression2? It doesn't seem logically possible, but I'm probably missing or misunderstanding something.
    – jbobbins
    Commented Sep 25, 2020 at 4:05
  • 2
    @jbobbins: If expression1 is false there is no need to evaluate expression2.
    – jesse_b
    Commented Sep 25, 2020 at 11:20
  • 4
    Wow, that's embarrassing... I guess my brain was locked into true mode. ;( Maybe it's time to retire :D
    – jbobbins
    Commented Sep 25, 2020 at 15:10

You can also use OR condition like this

if test "$fname" = "a.txt" || test "$fname" = "c.txt"
  • 7
    This is fundamentally the same as the accepted answer (and several comments) but more characters and (IMHO) less readable. Commented May 15, 2020 at 21:20
  • It is easier to read test than brackets. Why make the code more cryptic than necessary?
    – Massimo
    Commented May 27, 2020 at 15:12
  • 3
    That is your subjective opinion. Mine is that brackets are easier to read. None of our opinions is "correct", just saying. Commented Mar 2, 2021 at 9:22
  • 4
    Massimo, you’re replying under every answer stating that you think test is more convenient, yet nobody is upvoting these comments. How much cue do you need? You might think your way is best, but I think most people disagree. Sorry :)
    – MS Berends
    Commented Jul 21, 2021 at 11:56
  • @Massimo "more readable" is a subjective opinion. But [] and [[]] are clearly more idiomatic.
    – Barmar
    Commented Jan 26, 2022 at 19:23

You can use or condition like this

 if [ "$fname" = "a.txt" -o "$fname" = "c.txt" ]
  • 40
    Yes you can, but using -o for "or" is marked as obsolete in the POSIX standard, as is using -a for "and". New code should not use -o or -a.
    – Kusalananda
    Commented Jan 4, 2020 at 14:19
  • 2
    It also makes for unreliable code as the [ command is not always able to parse its arguments correctly when given more than 4 arguments (beside [ and ]). Try for instance with fname='!' with the [ builtin of the bash shell. Commented Jul 20, 2020 at 12:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .