Che $(cat file_list.txt)nelle shell POSIX come bashnel contesto dell'elenco sia l'operatore split + glob ( zshfa solo la parte divisa come ci si aspetterebbe).
Si divide su personaggi di $IFS(per impostazione predefinita, SPC , TAB e NL) e fa glob a meno che non si disattivi del tutto.
Qui, vuoi dividere solo su newline e non vuoi la parte glob, quindi dovrebbe essere:
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
Ciò ha anche il vantaggio (su un while readciclo) di scartare le linee vuote, preservare una linea non terminata finale e preservare lo mvstdin (necessario in caso di prompt, ad esempio).
Ha lo svantaggio, tuttavia, che l'intero contenuto del file deve essere archiviato in memoria (più volte con shell come bashe zsh).
Con alcune shell ( e ksh, zshin misura minore bash), puoi ottimizzarlo con $(<file_list.txt)invece di $(cat file_list.txt).
Per fare l'equivalente con un while readciclo, avresti bisogno di:
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 mve zsh:
mv -t -- new_place ${(f)"$(<file_list.txt)"}
O con GNU mve GNU xargse ksh / zsh / bash:
xargs -rd '\n' -a <(grep . file_list.txt) mv -t -- new_place
Altre informazioni su cosa significhi lasciare le espansioni non quotate alle implicazioni sulla sicurezza di dimenticare di citare una variabile nelle shell bash / POSIX