Looping Over Command Output
In this page:
The while read Idiom
while IFS= read -r line; do ... done <<< "$data" is the standard safe way to process text line by line: -r disables backslash interpretation, and IFS= stops leading/trailing whitespace from being stripped off each line. Feeding it via <<< (a here-string) keeps the loop running in the current shell rather than a subshell.
Example: The while read Idiom
#!/bin/bash
data=$'line one\nline two\nline three'
while IFS= read -r line; do
echo "Processing: $line"
done <<< "$data"
Login to try C/C++/Java/PHP code in the editor
Reading a File Line by Line
The same while read idiom works directly against a file using input redirection (< file) instead of a here-string, without ever loading the whole file into a variable first. This scales well even for large files since each line is read one at a time.
Example: Reading a File Line by Line
#!/bin/bash
printf "apple\nbanana\ncherry\n" > fruits.txt
while IFS= read -r line; do
echo "Fruit found: $line"
done < fruits.txt
Login to try C/C++/Java/PHP code in the editor
Looping Over Command Output with Process Substitution
Feeding while read from a command's output via process substitution, < <(command), avoids the subshell problem that piping (command | while read) causes, since the loop still runs in the current shell. This means variables set inside the loop remain visible after it finishes.
Example: Looping Over Command Output with Process Substitution
#!/bin/bash
total=0
while IFS= read -r num; do
total=$((total + num))
done < <(printf "1\n2\n3\n")
echo "Total after loop: $total"
Login to try C/C++/Java/PHP code in the editor
for word in $(command) for Simple Word Lists
When a command's output is known to be simple, whitespace-separated single-word tokens with no embedded spaces, for word in $(command); do ... done is a quick way to iterate over them. For anything line-structured or containing spaces, while read is the safer and more correct choice.
Warning: This pattern breaks on multi-word lines -- reach for while read whenever a line's meaning depends on keeping it whole.
Example: for word in $(command) for Simple Word Lists
#!/bin/bash
for status_code in $(printf "200 404 500"); do
echo "HTTP status: $status_code"
done
Login to try C/C++/Java/PHP code in the editor
- Using
for line in $(command)to loop over multi-word lines; this word-splits on every space and newline, mangling any line that contains more than one word --while readis the correct tool for line-based processing. - Piping into a
while readloop and then being confused that variables set inside the loop disappear afterward; a loop that is the receiving end of a pipe runs in a subshell, so its variable changes don't persist in the parent shell (process substitution avoids this, but that's a more advanced fix). - Forgetting
readstrips leading/trailing whitespace and interprets backslashes by default unless-r(raw mode) is used andIFSis adjusted -- omitting-rcan silently corrupt lines containing backslashes.
while IFS= read -r line; do ... done <<< "$data"(or< file) is the standard, safe idiom for processing text line by line.-rpreventsreadfrom interpreting backslash escapes;IFS=prevents it from trimming leading/trailing whitespace from each line.- Feeding a
while readloop via a pipe puts it in a subshell, so variables it sets are lost after the loop; using<<<or< filefor input instead keeps it in the current shell. for word in $(command)should be reserved for simple, known-safe, single-word-per-item output -- for anything line-oriented, preferwhile read.
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first: