-1

I try to get some data from sysin and here is my problem: if data are directed from a file, then the last line is not read. Example of text file:

line1
line2
line3

My code:

#!/bin/bash
while read line
do
  echo "$line"
done

And output:

$ ./test.sh < data.txt
line1
line2

If I write down at the end of my file null string output correct. But I don`t like it. How to fix this?

Nawy
  • 13
  • 1
  • 5
  • There are **lots** of duplicates for this one. Are you sure you tried to search for an existing answered question? See also: http://stackoverflow.com/questions/15485555/read-last-line-of-file-in-bash-script-when-reading-file-line-by-line, http://stackoverflow.com/questions/4165135/how-to-use-while-read-bash-to-read-the-last-line-in-a-file-if-there-s-no-new, http://stackoverflow.com/questions/16627578/bash-iterating-through-txt-file-lines-cant-read-last-line – Charles Duffy May 07 '16 at 17:58
  • sorry for my inadvertence – Nawy May 07 '16 at 18:09

3 Answers3

2

The idiom for this is:

while read -r line || [[ $line ]]; do
  : process "$line"
done

Thus, we proceed in the loop while either:

  • We read a valid line of text (which requires a newline)
  • We had a partial read (which results in a nonzero exit status, but leaves the variable non-empty).
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
1

If you need desperately to read files without EOL in the end, then you may check whether returned string is empty or not instead of checking read exit status:

#!/bin/bash
while true; do
  line=''
  read line
  if [ -z "$line" ]; then
    break
  fi
  echo "$line"
done
gudok
  • 4,029
  • 2
  • 20
  • 30
0

I bet you that data.txt is missing a trailing newline, try checking with

od -xa data.txt

Look at the end:

$ od -xa data.txt
0000000    696c    656e    0a31    696c    656e    0a32    696c    656e
          l   i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e
0000020    0033
          3
0000021

If you see the above you are missing the newline.

$ od -xa data-with-nl.txt
0000000    696c    656e    0a31    696c    656e    0a32    696c    656e
          l   i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e
0000020    0a33
          3  nl
0000022

Some shells will also show a % sign if trailing newline is missing, try:

$ cat data.txt
line1
line2
line3%
$
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123