Ibrahim Quraish
Ibrahim Quraish

Reputation: 4099

Unix read command behavior in file input redirection

Consider I have a file with contents available in it

cat file | read; echo $REPLY

gives empty output

read < file; echo $REPLY

gives first line of the file as result

while IFS= read; do :; done < file; echo $REPLY

prints nothing, empty output. I expected here the last line of the file as the ouput since I thought the iteration would occur till the end of the file is reached and the last line would be retained in REPLY variable. Any reason for this behavior?

Upvotes: 0

Views: 129

Answers (2)

John1024
John1024

Reputation: 113994

while IFS= read; do :; done < file; echo $REPLY

The above reads each line of the file, one by one. After it reads the last line of the file, it goes through the loop and then it tries to read once more. It is this last attempt to read that generates end-of-file condition and the empty $REPLY.

read < file; echo $REPLY

By default, read reads one line at a time. You only ask for one line so that is what is in $REPLY. (If one specifies the -d option to read, then $REPLY could have the whole file in it depending on the chosen delimiter.

cat file | read; echo $REPLY

This is a pipeline. This means that read is in a subshell. Therefore, shell variables that it creates do not survive.

If your goal is to get the last line of the file into a variable, there are options. For example:

reply="$(tail -n1 file)" ; echo $reply

Or,

reply="$(sed -n '$p' file )" ; echo $reply

(In sed-speak, $ means the last line of the file and p means print. So, $p means print the last line of the file.)

Upvotes: 1

anubhava
anubhava

Reputation: 786349

If you want to keep last line from file in REPLY variable using a while loop use this:

REPLY=
while read -r line; do
    REPLY="$line"
done < file

echo "REPLY=$REPLY"

Upvotes: 0

Related Questions