1

I am trying to create a small script that takes a filename, in which the absolute location of files are listed, and to copy it to some other location.

Content of the file test.txt for example:

/home/public/Music/Disk/GameOfThrones/Season1/01 Main Title.mp3

Script tried:

for file in `cat test.txt`; do cp "$file" temp ; done

However, this script thinks there are three files. Some more searching yield the following file:

OIFS="$IFS"
IFS=$'\n'
for file in `cat test.txt`; do cp "$file" temp ; done
IFS="$OIFS"

which seems to replace each occurrance of the letter 'n' by a newline.

So how to do it correctly?

Alex
  • 5,700

2 Answers2

3

Use a while loop with read, not for:

while read -r file ; do
    cp "$file" temp
done < test.txt
choroba
  • 47,233
1

Leaving `...` (or its newer form $(...)) unquoted is the split+glob operator.

The splitting part is done on the characters of $IFS, by default, SPC, TAB and newline. Here, you want to split on newline only, and don't want the glob part. So it's:

IFS='
' # split on newline only. IFS=$'\n' also works in some shells
set -o noglob # disable the glob part
cp -- $(cat test.txt) temp/

With zsh which has an explicit splitting operator, it can be simplified to:

cp -- ${(f)"$(cat test.txt)"} temp/

With GNU tools, you can also do:

xargs -d '\n' -ra test.txt cp -t temp

(which will also have the benefit to work around the limit on the size of the arguments in case there is a large number of files to copy).