What is the purpose of the do keyword in Bash for loop syntax? To me, it feels redundant.

for i in `seq 1 2`; do echo "hi"; done

Why isn't the syntax like this?

for i in `seq 1 2`; echo "hi"; done

I'm sure that it does fill a purpose. I just want to learn.


Note that that syntax is inherited from the Bourne shell.

After the variable name, you can have either in to have the list of elements explicitly given, or do, to loop over the positional parameters.

for i in 1 2 3
  echo "$i"


set 1 2 3
for i do
  echo "$i"

Having the do in both cases (even if it's not strictly necessary in the first one) makes for a more consistent syntax. It's also consistent with the while/until loops where the do is necessary.


You need the do to tell where the list of condition commands end.

Note that the Bourne shell did not support for i; do. That syntax was also not POSIX until the 2016 edition of the standard (for i do has always been POSIX; see the related Austin group bug).

zsh has a few shorthand forms like:

for i in 1 2 3; echo $i
for i (1 2 3) echo $i
for ((i=1;i<=3;i++)) echo $i

Or support for more than one variable:

for i j (1 a 2 b) echo $i $j

(though you can't use in or do as variable name in place of j above).

Even if rarely documented, most Bourne-like shells (Bourne, ksh, bash, zsh, not ash nor yash) also support:

for i in 1 2 3; { echo "$i";}

The Bourne shell, ksh and zsh (but not bash) also support:

for i { echo "$i"; }

While bash, ksh and zsh (but not the Bourne shell) support:

for i; { echo "$i"; }

All (Bourne, bash, ksh, zsh) support:

for i
{ echo "$i";}

ksh93, bash, zsh support:

for ((i=1;i<=3;i++)) { echo "$i"; }
  • 2
    As always, complete and perfect answer (with a reference to zsh)... – Kiwy Aug 31 '16 at 11:12
  • 2
    It's not "strictly necessary" in either case for for; the command could be terminated by a newline or semicolon. It makes a bit more sense for if/while (the former with then rather than do), but in principle those could have omitted it and required a subshell or braces for the (rare) use of multiple commands. I suspect the real reason that the Bourne shell does it is because ALGOL does it, and we should be glad that done isn't spelled od. – Random832 Aug 31 '16 at 13:47
  • 4
    @Random832: That's because od was already used as the name of the Octal Dump program. – user1024 Aug 31 '16 at 16:17
  • 8
    There is so much here I didn't know. Thank you! – Lightness Races in Orbit Aug 31 '16 at 17:49
  • 1
    @mirabilos, for i do is Bourne and POSIX, but won't work in some old versions of ash-based shells IIRC. for i in "$@" won't work in the Bourne shell if $IFS doesn't contain the space character. for i<newline>do is indeed the most portable if you need to consider very old BSD systems. See in-ulm.de/~mascheck/various/bourne_args for details – Stéphane Chazelas Sep 1 '16 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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