# Do the two styles of for-loops differ in what they can express?

There are two styles of syntax of for-loop:

``````for (( expr1 ; expr2 ; expr3 )) ; do commands ; done

for name [ [in [words ...] ] ; ] do commands; done
``````

At a glance, the kinds of looping that two can express seem unrelated to each other. the first one can express looping based on arithmetic expressions, while the second can express looping based on enumerating members in a set `words`.

Essentially, do they actually differ in what kinds of looping they can express, or are they equivalent to each other? If the former, when to use which?

The second form is always finite, the first can trivially be made an infinite loop:

``````for ((;;)); do echo \$SHELL; done
``````
• Can the first one always do what the second one can? – Tim Apr 24 '16 at 16:13
• @Tim indirectly, I'd say yes. You could do: `a=( words ); for ((i=0;i<\${#a[@]};i++)); name=\${a[i]}; …; done`. With a special case for `"\$@"`. – muru Apr 24 '16 at 16:19

The first

``````for (( expr1 ; expr2 ; expr3 )) ; do commands ; done
``````

is arguably more general than the second

``````for name [ [in [words ...] ] ; ] do commands; done
``````

because

• the variable(s) used in the expressions can be used as array indices (and obtain the selection from a list of words used in the second),
• but the second form uses an unchanging list of words to step through (but the first form uses an expression for ending the loop, which means that the loop-termination is not predetermined to the same extent).

This:

``````for (( expr1 ; expr2 ; expr3 )) ; do commands ; done
``````

Loops over integers, as it is forced to do so by the fact that inside the `(( ))` each part (divided by `;`) is an "Arithmetic expression".

It is similar to a `c` for loop, has start, end and "step action" defined in one line, it is more compact.

The second works on list of words, which could be numbers, strings or arrays:

``````for a in 1 2 3 4 5; do echo "\$a"; done
for a in one two three four five; do echo "\$a"; done
for a in "\${one[@]}" ; do echo "\$a"; done
``````

One caveat of this is that the list of words is subject to shell split, which is not an issue in the former construct.