根据输入列表、文件名中的特殊字符复制文件

根据输入列表、文件名中的特殊字符复制文件

这是基于问题这里

问题

  • 我有一个 .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

因此,循环仅执行一次,且文件名不存在。

相关内容