That unquoted $(cat file_list.txt) in POSIX shells like bash in list context is the split+glob operator (zsh only does the split part as you'd expect).
It splits on characters of $IFS (by default, SPC, TAB and NL) and does glob unless you turn off globbing altogether.
Here, you want to split on newline only and don't want the glob part, so it should be:
IFS='
' # split on newline only
set -o noglob # disable globbing
for file in $(cat file_list.txt); do # split+glob
mv -- "$file" "new_place/$file"
done
That also has the advantage (over a while read loop) to discard empty lines, preserve a trailing unterminated line, and preserve mv's stdin (needed in case of prompts for instance).
It does have the disadvantage though that the full content of the file has to be stored in memory (several times with shells like bash and zsh).
With some shells (ksh, zsh and to a lesser extent bash), you can optimise it with $(<file_list.txt) instead of $(cat file_list.txt).
To do the equivalent with a while read loop, you'd need:
while IFS= read <&3 -r file || [ -n "$file" ]; do
{
[ -n "$file" ] || mv -- "$file" "new_place/$file"
} 3<&-
done 3< file_list.txt
Or with bash:
readarray -t files < file_list.txt &&
for file in "${files[@]}"
[ -n "$file" ] || mv -- "$file" "new_place/$file"
done
Or with zsh:
for file in ${(f)"$(<file_list.txt)"}
mv -- "$file" "new_place/$file"
done
Or with GNU mv and zsh:
mv -t -- new_place ${(f)"$(<file_list.txt)"}
Or with GNU mv and GNU xargs and ksh/zsh/bash:
xargs -rd '\n' -a <(grep . file_list.txt) mv -t -- new_place
More reading about what it means to leave expansions unquoted at Security implications of forgetting to quote a variable in bash/POSIX shells