How do I iterate through each line of a text file with Bash?
With this script:
echo \"Start!\"
for p in (peptides.txt)
do
echo \"${p}\"
done
Suppose you have this file:
$ cat /tmp/test.txt
Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR
There are four elements that will alter the meaning of the file output read by many Bash solutions:
If you want the text file line by line including blank lines and terminating lines without CR, you must use a while loop and you must have an alternate test for the final line.
Here are the methods that may change the file (in comparison to what cat
returns):
1) Lose the last line and leading and trailing spaces:
$ while read -r p; do printf "%s\n" "'$p'"; done
(If you do while IFS= read -r p; do printf "%s\n" "'$p'"; done instead, you preserve the leading and trailing spaces but still lose the last line if it is not terminated with CR)
2) Using process substitution with cat
will reads the entire file in one gulp and loses the meaning of individual lines:
$ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
'Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR'
(If you remove the "
from $(cat /tmp/test.txt)
you read the file word by word rather than one gulp. Also probably not what is intended...)
The most robust and simplest way to read a file line-by-line and preserve all spacing is:
$ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done
If you want to strip leading and trading spaces, remove the IFS=
part:
$ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done
(A text file without a terminating \n
, while fairly common, is considered broken under POSIX. If you can count on the trailing \n
you do not need || [[ -n $line ]]
in the while
loop.)
More at the BASH FAQ