Existem várias opções; este é um:
cat filelist.txt | while read file; do
cp "$file" newfolder
done
Então, primeiro porque
for file in $(cat filelist.txt); do cp "$file" newfolder; done
não funciona? Suponha que sua lista de arquivos contenha
a
b c
O $(cat filelist.txt)
produz uma lista de nomes de arquivos. O loop for vê a saída de cat
e interpreta como:
for file in a b c ; do
que claramente não é a intenção.
É aqui que o comentário sobre o Separador do campo de entrada ajuda. Normalmente, o IFS é qualquer espaço em branco e, portanto, um espaço no nome do arquivo será interpretado como uma separação entre nomes de arquivos. Se você definir o IFS explicitamente como uma nova linha, o espaço não será mais visto como um separador.
for file in "$(cat filelist.txt)"; do cp "$file" newfolder; done
cria um único argumento para o loop for. O resultado é equivalente a:
for file in "a b c" ; do
e, portanto, o loop é executado apenas uma vez, com um nome de arquivo que não existe.