É apenas uma consequência de como a gramática é definida. Na especificação de gramática POSIX Shell :
command : simple_command
| compound_command
| compound_command redirect_list
| function_definition
;
E:
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 você pode ver, com comandos compostos, o redirecionamento é permitido apenas depois , mas com comandos simples, também é permitido antes. Portanto, quando o shell vê <redirection> foo
, foo
é tratado como um comando simples, não como um comando composto e while
não é mais tratado como uma palavra-chave:
$ < foo while
bash: while: command not found
Portanto, o do
é inesperado, pois só é permitido após determinadas palavras-chave.
Portanto, isso se aplica não apenas aos while
loops, mas à maioria das maneiras de configurar comandos compostos usando palavras reservadas:
$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found