Why do I need to place “do” in the same line as “for”?

Syntactically, the following two code snippets are correct and equivalent:

for f in bash/*.sh; do
    sashacommand "$f"
done
for f in bash/*.sh
    do sashacommand "$f"
done

The latter one could possibly be said to be harder to read as do slightly obfuscates the command in the body of the loop. If the loop contains multiple commands and the next command is on a new line, the obfuscation would be further highlighted:

for f in *
    do cmd1
    cmd2
done

... but to flag it as an "error" is IMHO someone's personal opinion rather than an objective truth.

I would say that if you want to prepend the command in the loop with do, then feel free to do so if that makes the code consistent and readable in the eyes of whoever is reading the code.

In general, almost any ; may be replaced by a newline. Both ; and newline are command terminators. do is a keyword that means "here follows what needs to be done (in this for loop)".

for f in *; do ...; done

is the same as

for f in *
do
   ...
done

and as

for f in *; do
   ...
done

and

for f in *
   do ...
done

The reason to use one over another is readability and local/personal style conventions.


Personal opinion:

In loop headers that are very long, I think that it may make sense to put do on a new line, as in

for i in animals people houses thoughts basketballs bees
do
    ...
done

or

for i in        \
    animals     \
    people      \
    houses      \
    thoughts    \
    basketballs \
    bees
do
    ...
done

The same goes for the then in an if statement.

But again, this comes down to one's personal style preferences, or to whatever coding style one's team/project is using.


Note what it says on the top of the page:

bashate: A pep8 equivalent for bash scripts

PEP8 is the Style Guide for Python Code. While Python folks often seem to take their style issues very seriously[citation needed], it's just that, a guide. We could come up with upsides for both putting the do in the same line as the for, and for putting it on a line of its own.

It's the same discussion as where to put the { in C code when starting an if or while block (or such).


A few lines below in the documentation, there's another interesting rule:

E020: Function declaration not in format ^function name {$

I assume the point here is that the author of that style guide thinks that using the function keyword is necessary for the reader to recognise a function declaration. However, function foo is a non-standard way of defining a function: the standard way is foo(). The only difference between the two (in Bash) is that the other is harder to port to a standard shell, like /bin/sh in Debian or Ubuntu.

So, I would suggest taking any and all such style guides with a grain of salt or three, and deciding for yourself what the best style is. A good style-checker allows disabling some checks (bashate has bashate -i E010,E011 to ignore those two checks.) An excellent style-checker would allow you to modify the tests, e.g. to check for the opposite of E020, here.


TL;DR: You don't need to. It's just some dude's opinion.

Like many others, I've been writing for loops like this for decades:

for F in arg1 arg2 arg*
do
    somecommand "$F"
done

This layout highlights the fact that do ... done surround the loop body, like curly braces in C-like languages, and allows newlines to separate the loop construct's components.

Of course there are religious wars about where to place the curly braces too, so you might say the jury is still out on this one. IMHO, this is clearly how this was designed to work; Bourne was fond of matched delimiters, cf. if ... fi, case ... esac, and the need for a semicolon in the shorter version reveals that you're making it shorter than originally designed. Nothing wrong with that; technology advances and a lot of things that once seemed like a good idea are now frowned upon, like goto. But until the entire shell-scripting community adopts the preferences of the bashate author(s), you don't have to do a thing.