The best way to do this is to redirect the file into the loop:
# Basic idea. Keep reading for improvements.
FILE=test
while read CMD; do
echo "$CMD"
done < "$FILE"
A redirection with < "$FILE"
has a few advantages over cat "$FILE" | while ...
. It avoids a useless use of cat, saving an unnecessary child process. It also avoids a common pitfall where the loop runs in a subshell. In Bash, commands in a |
pipeline run in subshells, which means variable assignments are lost after the loop ends. Redirection with <
doesn't have that problem, so you could use $CMD
after the loop or modify other variables inside the loop. It also, again, avoids unnecessary child processes.
There are some additional improvements that could be made:
- Add
IFS=
so that read
won't trim leading and trailing whitespace from each line.
- Add
-r
to read
to prevent backslashes from being interpreted as escape sequences.
- Lower-case
CMD
and FILE
. The Bash convention is that only environmental and internal shell variables are uppercase.
- Use
printf
in place of echo
which is safer if $cmd
is a string like -n
, which echo
would interpret as a flag.
file=test
while IFS= read -r cmd; do
printf '%s
' "$cmd"
done < "$file"
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…