पाठ 9 / 25
for, while and Reading Lines Safely
Loop over values, files and lines without breaking on spaces.
Iterating correctly
for item in list; do ...; done iterates over words: for f in *.csv loops over files matching a glob (each file name stays intact even with spaces, because globbing produces separate words), and for arg in "$@" loops over arguments. C-style loops count: for (( i = 0; i < 5; i++ )). while condition; do ...; done repeats while a command succeeds, and until while it fails, useful for retries. To process a file or command output line by line, use while IFS= read -r line; do ...; done < file: IFS= keeps leading and trailing spaces, and -r keeps backslashes literal. Do not use for line in $(cat file), which splits on every space and expands globs. When piping into while, note that the loop runs in a subshell in Bash, so variables set inside are lost afterwards; feed the loop with < file or < <(command) instead. break and continue control loop flow; enable shopt -s nullglob so a glob with no matches expands to nothing instead of the literal pattern.
Safe loops over files and lines
Globs and read -r handle awkward names and lines correctly.
shopt -s nullglob # no matches -> empty list, not literal "*.csv"
for f in /data/incoming/*.csv; do
echo "processing: $f"
done
total=0
while IFS= read -r line; do
[[ -z $line || $line == \#* ]] && continue # skip blanks and comments
total=$(( total + 1 ))
done < hosts.txt
echo "hosts: $total" # works: the loop did not run in a subshell
# reading command output without losing variables
while IFS=, read -r user email; do
echo "$user <$email>"
done < <(grep -v '^#' users.csv)
attempt=0
until curl -fsS https://example.com/health > /dev/null; do
(( ++attempt >= 5 )) && { echo "giving up" >&2; exit 1; }
sleep $(( attempt * 2 ))
donecat | while loses your variables
cat file | while read -r line; do count=$((count+1)); done leaves count unchanged afterwards, because the loop ran in a subshell. Redirect the file into the loop instead.
त्वरित जाँच: Why is `while IFS= read -r line` preferred for reading lines?
- It is faster than every other method
- It reads the whole file into memory at once
- It preserves spaces and backslashes exactly as they appear in each line
- It sorts the lines
Answer
It preserves spaces and backslashes exactly as they appear in each line — Empty IFS keeps surrounding whitespace and -r stops backslash interpretation.