Che $(cat file_list.txt)
nelle shell POSIX come bash
nel contesto dell'elenco sia l'operatore split + glob ( zsh
fa 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 read
ciclo) di scartare le linee vuote, preservare una linea non terminata finale e preservare lo mv
stdin (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 bash
e zsh
).
Con alcune shell ( e ksh
, zsh
in misura minore bash
), puoi ottimizzarlo con $(<file_list.txt)
invece di $(cat file_list.txt)
.
Per fare l'equivalente con un while read
ciclo, 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 mv
e zsh
:
mv -t -- new_place ${(f)"$(<file_list.txt)"}
O con GNU mv
e GNU xargs
e 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