In Bash you can move input redirection operators to the front of a command:

cat <<< "hello"
# equivalent to
<<< "hello" cat

Why are you unable to do the same for while loops?

while read -r line; do echo "$line"; done <<< "hello"
# hello

<<< "hello" while read -r line; do echo "$line"; done
# -bash: syntax error near unexpected token `do'

I find it a bit confusing since you can pipe into a while loop. Am I doing something wrong or was it just a design decision?

1 Answer 1


It's just a consequence of how the grammar is defined. From the POSIX Shell Grammar specification:

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

As you can see, with compound commands, redirection is only allowed after, but with simple commands, it is allowed before as well. So, when the shell sees <redirection> foo, foo is treated as a simple command, not a compound command, and while is no longer treated as a keyword:

$ < foo while
bash: while: command not found

Hence, the do is unexpected, since it's only allowed after certain keywords.

So this applies not just to while loops, but most of the ways of setting up compound commands using reserved words:

$ < foo {
bash: {: command not found
$ < foo if
bash: if: command not found
$ < foo for
bash: for: command not found
  • Nice explanation, thank you.
    – philraj
    Aug 26, 2019 at 18:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .