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 thatreadwon’t trim leading and trailing whitespace from each line. - Add
-rtoreadto prevent backslashes from being interpreted as escape sequences. - Lower-case
CMDandFILE. The Bash convention is that only environmental and internal shell variables are uppercase. - Use
printfin place ofechowhich is safer if$cmdis a string like-n, whichechowould interpret as a flag.
file=test
while IFS= read -r cmd; do
printf '%s\n' "$cmd"
done < "$file"