Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I'm trying to get a simple while loop working in bash that uses two conditions, but after trying many different syntax from various forums, I can't stop throwing an error. Here is what I have:

while [ $stats -gt 300 ] -o [ $stats -eq 0 ]

I have also tried:

while [[ $stats -gt 300 ] || [ $stats -eq 0 ]]

... as well as several others constructs. I want this loop to continue while $stats is > 300 or if $stats = 0.

share|improve this question

3 Answers 3

up vote 37 down vote accepted

The correct options are (in increasing order of recommendation):

# Single POSIX test command with -o operator (not recommended anymore).
# Quotes strongly recommended to guard against empty or undefined variables.
while [ "$stats" -gt 300 -o "$stats" -eq 0 ]

# Two POSIX test commands joined in a list with ||.
# Quotes strongly recommended to guard against empty or undefined variables.
while [ "$stats" -gt 300 ] || [ "$stats" -eq 0 ]

# Two bash conditional expressions joined in a list with ||.
while [[ $stats -gt 300 ]] || [[ $stats -eq 0 ]]

# A single bash conditional expression with the || operator.
while [[ $stats -gt 300 || $stats -eq 0 ]]

# Two bash arithmetic expressions joined in a list with ||.
# $ optional, as a string can only be interpreted as a variable
while (( stats > 300 )) || (( stats == 0 ))

# And finally, a single bash arithmetic expression with the || operator.
# $ optional, as a string can only be interpreted as a variable
while (( stats > 300 || stats == 0 ))

Some notes:

  1. Quoting the parameter expansions inside [[ ... ]] and ((...)) is optional; if the variable is not set, -gt and -eq will assume a value of 0.

  2. Using $ is optional inside (( ... )), but using it can help avoid unintentional errors. If stats isn't set, then (( stats > 300 )) will assume stats == 0, but (( $stats > 300 )) will produce a syntax error.

share|improve this answer
    
+1 for good answer + (close to ?) exhaustive – Gilles Quenot Mar 20 '13 at 22:37
    
Fantastic answer, amazingly thorough – jake9115 Mar 21 '13 at 14:49
    
Bravo. a classic way to answer a post. Well done. I'm assuming you can use the same syntax with until as well, yes? – SaxDaddy Aug 14 '14 at 21:05
    
@SaxDaddy More or less, as long as you take care to negate the conditions correctly: while [ foo -o bar ] becomes until ! [ foo -o bar ], but while foo || bar becomes until ! foo && ! bar. – chepner Aug 14 '14 at 21:19

Try:

while [ $stats -gt 300 -o $stats -eq 0 ]

[ is a call to test. It is not just for grouping, like parentheses in other languages. Check man [ or man test for more information.

share|improve this answer
1  
I recommend [[ over [. See my comment on the other answer. – danfuzz Mar 20 '13 at 21:50
    
That's fair. I used [ ] because that was what the OP was trying to use. I've seen both used with success. – drewmm Mar 20 '13 at 21:59

The extra [ ] on the outside of your second syntax are unnecessary, and possibly confusing. You may use them, but if you must you need to have whitespace between them.

Alternatively:

while [ $stats -gt 300 ] || [ $stats -eq 0 ]
share|improve this answer
    
Actually, [[ is generally the preferred built-in to introduce a test expression. It has several advantages over the older single [ syntax. – danfuzz Mar 20 '13 at 21:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.