Nunca use for foo in $(cat bar)
. Este é um erro clássico, comumente conhecido como pitfall número 1 . Você deve usar:
while IFS= read -r file; do mv -- "$file" "new_place/$file"; done < file_list.txt
Quando você executar o loop for
, o bash aplicará o wordsplit ao que lê, o que significa que a strange blue cloud
será lido como a
, strange
, blue
e cloud
:
$ cat files
a strange blue cloud.txt
$ for file in $(cat files); do echo "$file"; done
a
strange
blue
cloud.txt
Compare com:
$ while IFS= read -r file; do echo "$file"; done < files
a strange blue cloud.txt
Ou mesmo, se você insistir na UUoC :
$ cat files | while IFS= read -r file; do echo "$file"; done
a strange blue cloud.txt
Portanto, o loop while
lerá sua entrada e usará o read
para atribuir cada linha a uma variável. O IFS=
define o separador do campo de entrada como NULL * e a opção -r
de read
impede que ele interprete escapes de barra invertida (para que \t
seja tratado como barra + t
e não como uma guia). O --
após o mv
significa "tratar tudo após o - como um argumento e não como uma opção", o que permite lidar com nomes de arquivos que começam com -
corretamente.
* Isto não é necessário aqui, estritamente falando, o único benefício neste cenário é que mantém read
de remover qualquer espaço em branco inicial ou final, mas é um bom hábito para entrar em quando você precisa lidar com nomes de arquivos contendo caracteres de nova linha, ou em geral, quando você precisa ser capaz de lidar com nomes de arquivos arbitrários.