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
do
echo "$i"
done
Or
set 1 2 3
for i do
echo "$i"
done
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.
while
cmd1
cmd2
do
cmd3
cmd4
done
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"; }
for
; the command could be terminated by a newline or semicolon. It makes a bit more sense forif
/while
(the former withthen
rather thando
), 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 thatdone
isn't spelledod
. – Random832 Aug 31 '16 at 13:47od
was already used as the name of the Octal Dump program. – user1024 Aug 31 '16 at 16:17for
without thein
defaults to positional parameters. – h.j.k. Sep 01 '16 at 03:49for i
do
” is portable (the one-line form, with or without semicolon, isn’t) in the shorthand, though (“for i in "$@"; do
is POSIX).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 http://www.in-ulm.de/~mascheck/various/bourne_args/ for details – Stéphane Chazelas Sep 01 '16 at 11:30