C'est juste une conséquence de la façon dont la grammaire est définie. De la spécification POSIX Shell Grammar :
command : simple_command
| compound_command
| compound_command redirect_list
| function_definition
;
Et:
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
;
Comme vous pouvez le voir, avec les commandes composées, la redirection n'est autorisée qu'après , mais avec les commandes simples, elle est également autorisée avant. Ainsi, lorsque le shell voit <redirection> foo
, foo
est traité comme une commande simple, pas une commande composée, et while
n'est plus traité comme un mot-clé:
$ < foo while
bash: while: command not found
Par conséquent, le do
est inattendu, car il n'est autorisé qu'après certains mots clés.
Cela s'applique donc non seulement aux while
boucles, mais à la plupart des façons de configurer des commandes composées à l'aide de mots réservés:
$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found