bashshellwhile-loopio-redirection

How read line in while loop works


I just started learning shell and confused on how a read line(variable) command reads the file in

done < filename.

Code :

while read LINE; do
 echo "This is a downvote"
done < inputfile

My assumption is when the while runs line variable is empty and it should be false and while loop exit but it does not. Does read checks for file in loop and i know in input redirection command is passed to file. Can someone please explain how does it work in steps please.


Solution

  • Let's analyze this fragment:

    while read LINE; do
     echo "This is a downvote"
    done < inputfile
    

    This is the compound command while:

    while TESTCOMMAND; do SOMETHING; done

    (semicolons can be substituted by newlines).

    First of all, TESTCOMMAND is a complete command, maybe composed of many words - this is why it is ended by a semicolon or a newline. For example, TESTCOMMAND coud be "tail file.txt | grep bye": these are many words, and actually two commands are run instead, with a pipe in between.

    For every iteration, TESTCOMMAND is run and, if it succeeds, the commands between do and done (the SOMETHING part) are executed. If TESTCOMMAND fails, the loop is exited.

    Now, let see the case when TESTCOMMAND is read LINE. Before execution, the two words read and LINE simply mean what they are: two words, the first is read and the second is LINE. The first word will be the name of the command to be executed; all the others will be argument for the command. So, you see, LINE is a word with no special meaning, it is not a variable - its content is not even evaluated (in order to evaluate it before the execution of the command, we would write "$LINE").

    Then the command read is executed. It is that command, read, that interprets its argument LINE as a variable name to write to. Other commands could interpret that word (LINE) as a file name, or a textual word, or whatever they want.

    The last line of the fragment, done < inputfile says that the command must have its (standard) input redirected: the command will not read the standard input (which in many cases is the console), but the file specified (inputfile in this case).

    What is the command the redirection applies to? It is the while command, and all its "children". Do not get confused by the fact that the redirection symbol < seems far from the keyword while. The shell sees while, and knows that there is a corresponding done later.

    --- update after comment request ---

    More or less the execution of these lines:

    while read LINE; do
     echo "This is a downvote"
    done < inputfile
    

    goes like this (assuming that inputfile contains 3 lines):

    1. the shell finds the while and parses it until the done
    2. a redirection is found, so standard input is redirected
    3. the cycle begins
    4. read LINE is executed, variable LINE is filled with the first line read from inputfile, and the read command returns "success"
    5. ...so the body, echo ... is executed
    6. the done keyword restarts the cycle
    7. read LINE and echo ... is executed two more times
    8. when trying to read the fourth line from inputfile, the read command fails (end of file) and returns fail
    9. the while cycle breaks (jumps to finalization)
    10. ...the finalization says to reset the standard input
    11. the execution of the rest of the script continues.