Use um loop while
com read
, não for
:
while read -r file ; do
cp "$file" temp
done < test.txt
Estou tentando criar um script pequeno que usa um nome de arquivo, no qual a localização absoluta dos arquivos está listada e copiá-lo para outro local.
Conteúdo do arquivo test.txt
, por exemplo:
/home/public/Music/Disk/GameOfThrones/Season1/01 Main Title.mp3
Script testado:
for file in 'cat test.txt'; do cp "$file" temp ; done
No entanto, esse script acha que há três arquivos. Mais algumas pesquisas geram o seguinte arquivo:
OIFS="$IFS"
IFS=$'\n'
for file in 'cat test.txt'; do cp "$file" temp ; done
IFS="$OIFS"
que parece substituir cada ocorrência da letra 'n' por uma nova linha.
Então, como fazer isso corretamente?
Use um loop while
com read
, não for
:
while read -r file ; do
cp "$file" temp
done < test.txt
Deixar '...'
(ou sua nova forma $(...)
) sem aspas é o operador split + glob.
A parte de divisão é feita nos caracteres de $IFS
, por padrão, SPC, TAB e nova linha. Aqui, você quer dividir apenas na nova linha e não quer a parte glob. Então é:
IFS='
' # split on newline only. IFS=$'\n' also works in some shells
set -o noglob # disable the glob part
cp -- $(cat test.txt) temp/
Com zsh
, que tem um operador de divisão explícito, pode ser simplificado para:
cp -- ${(f)"$(cat test.txt)"} temp/
Com as ferramentas GNU, você também pode fazer:
xargs -d '\n' -ra test.txt cp -t temp
(que também terá o benefício de contornar o limite do tamanho dos argumentos, caso haja um grande número de arquivos para copiar).