Que $(cat file_list.txt)
en los shells POSIX como bash
en el contexto de la lista es el operador split + glob ( zsh
solo 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 read
bucle) de descartar líneas vacías, preservar una línea final no terminada y preservar mv
la 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 bash
y zsh
).
Con algunos shells ( y ksh
, zsh
en menor medida bash
), puede optimizarlo en $(<file_list.txt)
lugar de hacerlo $(cat file_list.txt)
.
Para hacer el equivalente con un while read
bucle, 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 mv
y zsh
:
mv -t -- new_place ${(f)"$(<file_list.txt)"}
O con GNU mv
y GNU xargs
y 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