Reading a File Line by Line
In this page:
The Standard while-read Idiom
Redirecting a file into a while read loop with < file after done reads one line per iteration until end-of-file, without needing a subshell. IFS= read -r preserves whitespace and disables backslash escaping.
Example: The Standard while-read Idiom
#!/bin/bash
printf "apple\nbanana\ncherry\n" > fruits.txt
while IFS= read -r line; do
echo "Fruit: $line"
done < fruits.txt
rm -f fruits.txt
Login to try C/C++/Java/PHP code in the editor
Why Piping Loses Variables
Piping a command into while read, like cat file | while read line; do ...; done, runs the loop in a subshell because it is on the right side of a pipe. Any variables changed inside that loop disappear once the loop finishes.
Warning: If you need to accumulate state while reading a file, use < file redirection, not a pipe, into the while loop.
Example: Why Piping Loses Variables
#!/bin/bash
printf "1\n2\n3\n" > numbers.txt
count=0
cat numbers.txt | while read -r n; do
count=$((count + 1))
done
echo "count after piped loop (lost): $count"
count=0
while read -r n; do
count=$((count + 1))
done < numbers.txt
echo "count after redirected loop (kept): $count"
rm -f numbers.txt
Login to try C/C++/Java/PHP code in the editor
Reading the Last Line Without a Trailing Newline
If a file's last line has no trailing newline, plain read still succeeds in returning that final line's text but returns a non-zero status, which can cause the loop body to be skipped. Checking || [[ -n $line ]] handles that edge case.
Example: Reading the Last Line Without a Trailing Newline
#!/bin/bash
printf "one\ntwo\nthree" > no_trailing_newline.txt
while IFS= read -r line || [[ -n "$line" ]]; do
echo "Got: $line"
done < no_trailing_newline.txt
rm -f no_trailing_newline.txt
Login to try C/C++/Java/PHP code in the editor
- Piping into a
while readloop and then wondering why variables set inside the loop don't exist after it; a piped loop runs in a subshell. - Forgetting
IFS=beforeread, which trims leading/trailing whitespace from each line unexpectedly. - Using
for line in $(cat file)instead ofwhile read; theforversion splits on whitespace and breaks on lines containing spaces.
while IFS= read -r line; do ... done < fileis the standard, safe idiom for reading a file line by line.- Redirecting the file with
< fileafterdonekeeps the loop in the current shell, unlike piping into it. IFS=prevents leading/trailing whitespace from being stripped from each line.readreturns non-zero on end-of-file, which naturally ends thewhileloop.
Chapter Quiz — Complete all 13 topics to unlock
0/13 topics done
Complete these topics first: