Es solo una consecuencia de cómo se define la gramática. De la especificación POSIX Shell Grammar :
command : simple_command
| compound_command
| compound_command redirect_list
| function_definition
;
Y:
simple_command : cmd_prefix cmd_word cmd_suffix
| cmd_prefix cmd_word
| cmd_prefix
| cmd_name cmd_suffix
| cmd_name
;
[...]
cmd_prefix : io_redirect
| cmd_prefix io_redirect
| ASSIGNMENT_WORD
| cmd_prefix ASSIGNMENT_WORD
;
cmd_suffix : io_redirect
| cmd_suffix io_redirect
| WORD
| cmd_suffix WORD
;
Como puede ver, con comandos compuestos, la redirección solo se permite después , pero con comandos simples, también se permite antes. Entonces, cuando el shell ve <redirection> foo
, foo
se trata como un comando simple, no como un comando compuesto, y while
ya no se trata como una palabra clave:
$ < foo while
bash: while: command not found
Por lo tanto, do
es inesperado, ya que solo se permite después de ciertas palabras clave.
Entonces, esto se aplica no solo a los while
bucles, sino a la mayoría de las formas de configurar comandos compuestos usando palabras reservadas:
$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found