Это всего лишь следствие того, как определяется грамматика. Из спецификации грамматики оболочки POSIX :
command : simple_command
| compound_command
| compound_command redirect_list
| function_definition
;
И:
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
;
Как вы можете видеть, с составными командами перенаправление разрешено только после , но с простыми командами, оно также разрешено и раньше. Таким образом, когда оболочка видит <redirection> foo
, foo
обрабатывается как простая команда, а не как составная команда, и while
больше не рассматривается как ключевое слово:
$ < foo while
bash: while: command not found
Следовательно, do
это неожиданно, так как это разрешено только после определенных ключевых слов.
Так что это относится не только к while
циклам, но и к большинству способов установки составных команд с использованием зарезервированных слов:
$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found