这是基于问题这里。
问题:
- 我有一个 .txt 文件,其中列出了我想要复制到该文件夹的文件名新建文件夹在 shell(Mac 终端)中。
方法, 在哪里文件列表.txt包含我要复制的文件名(以 \n 分隔):
# version 1
for file in $(cat filelist.txt); do cp "$file" newfolder; done
错误:
如果我有文件名文件列表.txt包含破折号、空格等的名称被分开,我正确地得到了一个No such file
错误。
以下是我尝试解决该问题的方法(向变量添加 dbl 引号):
# version 2
for file in "$(cat filelist.txt)"; do cp "$file" newfolder; done
但这会打印出所有文件名(没有空格分割)并且不会复制任何内容。
问题:
如上所述添加引号可以解决名称拆分问题,例如当我将其提供给
echo
;时为什么它不起作用cp
?cat
使用and执行此操作的正确方法是什么cp
?上面链接的答案中的评论表明以下内容:set -f;IFS=$'\n'
它可以解决问题,但我不知道它是做什么的。
非常感谢任何提示!
答案1
有多种选择;这是一:
cat filelist.txt | while read file; do
cp "$file" newfolder
done
那么,首先为什么
for file in $(cat filelist.txt); do cp "$file" newfolder; done
不行?假设您的文件列表包含
a
b c
生成$(cat filelist.txt)
文件名列表。 for 循环查看 的输出cat
并将其解释为:
for file in a b c ; do
这显然不是本意。
这就是有关输入字段分隔符的注释所提供的帮助。通常,IFS 是任意空格,因此文件名中的空格将被解释为文件名之间的分隔符。如果将 IFS 显式设置为换行符,则空格不再被视为分隔符。
for file in "$(cat filelist.txt)"; do cp "$file" newfolder; done
为 for 循环创建单个参数。结果相当于:
for file in "a b c" ; do
因此,循环仅执行一次,且文件名不存在。