You've run into an odd corner case of the shell grammar. What you really want is
for i in 1 2; do sleep 2 & done
with no ;
after the &
. You can put an extra newline here (as you've discovered), but its not necessary.
As to why you can't have a semicolon here, that's an odd artifact of the way command lists are defined -- they are one or more pipelines separated by the tokens ;
, &
, &&
, or ||
. However, within the list, you can't have any empty commands, so when you have & ;
with nothing between, that's an empty command in the middle of a list.
Note that you can have empty commands in other places. In addition, you can have one or more newlines after any of the above separators, or instead of a ;
. So it ends up seeming like you can have empty commands anywhere, but it turns out there are a few odd places they won't work (and will cause syntax errors)