Bahwa $(cat file_list.txt)
dalam shell POSIX seperti bash
dalam konteks daftar adalah operator split + glob ( zsh
hanya melakukan bagian split seperti yang Anda harapkan).
Itu terbagi pada karakter $IFS
(secara default, SPC , TAB dan NL) dan melakukan glob kecuali Anda mematikan globbing sama sekali.
Di sini, Anda ingin membagi hanya pada baris baru dan tidak ingin bagian glob, jadi seharusnya:
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
Itu juga memiliki keuntungan (lebih dari satu while read
loop) untuk membuang garis kosong, mempertahankan garis trailing yang tidak ditentukan, dan mempertahankan mv
stdin (diperlukan jika diminta misalnya).
Itu memang memiliki kekurangan meskipun isi penuh file harus disimpan dalam memori (beberapa kali dengan kerang seperti bash
dan zsh
).
Dengan beberapa shell ( ksh
, zsh
dan pada tingkat lebih rendah bash
), Anda dapat mengoptimalkannya dengan $(<file_list.txt)
alih - alih $(cat file_list.txt)
.
Untuk melakukan hal yang sama dengan while read
loop, Anda perlu:
while IFS= read <&3 -r file || [ -n "$file" ]; do
{
[ -n "$file" ] || mv -- "$file" "new_place/$file"
} 3<&-
done 3< file_list.txt
Atau dengan bash
:
readarray -t files < file_list.txt &&
for file in "${files[@]}"
[ -n "$file" ] || mv -- "$file" "new_place/$file"
done
Atau dengan zsh
:
for file in ${(f)"$(<file_list.txt)"}
mv -- "$file" "new_place/$file"
done
Atau dengan GNU mv
dan zsh
:
mv -t -- new_place ${(f)"$(<file_list.txt)"}
Atau dengan GNU mv
dan GNU xargs
dan ksh / zsh / bash:
xargs -rd '\n' -a <(grep . file_list.txt) mv -t -- new_place
Lebih banyak membaca tentang apa artinya membiarkan ekspansi tidak dikutip di Implikasi keamanan lupa mengutip variabel dalam bash / POSIX shells