Let’s say I have the following Bash script:
while read SCRIPT_SOURCE_LINE; do
echo "$SCRIPT_SOURCE_LINE"
done
I noticed that for files without a newline at the end, this will effectively skip the last line.
I’ve searched around for a solution and found this:
When read reaches end-of-file instead of end-of-line, it does read in the data and assign it to the variables, but it exits with a non-zero status. If your loop is constructed "while read ;do stuff ;done
So instead of testing the read exit status directly, test a flag, and have the read command set that flag from within the loop body. That way regardless of reads exit status, the entire loop body runs, because read was just one of the list of commands in the loop like any other, not a deciding factor of if the loop will get run at all.
DONE=false until $DONE ;do read || DONE=true # process $REPLY here done < /path/to/file.in
How can I rewrite this solution to make it behave exactly the same as the while
loop I was having earlier, i.e. without hardcoding the location of the input file?
I use the following construct:
while IFS= read -r LINE || [[ -n "$LINE" ]]; do
echo "$LINE"
done
It works with pretty much anything except null characters in the input: