Que $(cat file_list.txt)en los shells POSIX como bashen el contexto de la lista es el operador split + glob ( zshsolo hace la parte dividida como cabría esperar).
Se divide en caracteres de $IFS(de forma predeterminada, SPC , TAB y NL) y se globaliza a menos que desactive el globbing por completo.
Aquí, desea dividir solo en nueva línea y no desea la parte global, por lo que debería ser:
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
Eso también tiene la ventaja (sobre un while readbucle) de descartar líneas vacías, preservar una línea final no terminada y preservar mvla entrada estándar (necesaria en caso de avisos, por ejemplo).
Sin embargo, tiene la desventaja de que el contenido completo del archivo debe almacenarse en la memoria (varias veces con shells como bashy zsh).
Con algunos shells ( y ksh, zshen menor medida bash), puede optimizarlo en $(<file_list.txt)lugar de hacerlo $(cat file_list.txt).
Para hacer el equivalente con un while readbucle, necesitarías:
while IFS= read <&3 -r file || [ -n "$file" ]; do
{
[ -n "$file" ] || mv -- "$file" "new_place/$file"
} 3<&-
done 3< file_list.txt
O con bash:
readarray -t files < file_list.txt &&
for file in "${files[@]}"
[ -n "$file" ] || mv -- "$file" "new_place/$file"
done
O con zsh:
for file in ${(f)"$(<file_list.txt)"}
mv -- "$file" "new_place/$file"
done
O con GNU mvy zsh:
mv -t -- new_place ${(f)"$(<file_list.txt)"}
O con GNU mvy GNU xargsy ksh / zsh / bash:
xargs -rd '\n' -a <(grep . file_list.txt) mv -t -- new_place
Más información sobre lo que significa dejar las expansiones sin citar en Implicaciones de seguridad al olvidar citar una variable en bash / POSIX shells