如何正确使用 xargs 和 cp

How to Properly Use xargs With cp

我想做的是从索引文件中读取文件名列表,然后将每个列出的文件复制到另一个目录,但我在正确地将 xargs 和 cp 串在一起时遇到了一些麻烦。

head -n 150 ../indexes/index.txt | xargs cp ~/path/to/destination/

这会产生以下错误:

cp: target 'foo.txt': Not a directory

其中 foo.txt 是 index.txt 中列出的第 150 个文件名。显然 cp 应该将 xargs 的输入作为其第一个操作数而不是第二个操作数,但我如何才能做到这一点?

xargs 有一个 -I 参数,它本质上允许您指定替换模式并在命令中编写替换模式(在您的情况下为 cp)。然后,当执行该命令时,该替换模式的所有实例都将替换为下一行输入。因此,您的命令字符串应如下所示:

head -n 150 ../indexes/index.txt | xargs -I {} cp {} ~/path/to/destination/

如果没有 -Icp 只会将第二行输入视为目标,这不是预期的结果。

更新: 所以,对正在发生的事情进行细分: 当从 head 读取每一行输入时,因为您已经设置了一个管道,所以 head 的输出进入管道。当 xargs 从管道获取新行时,因为您指定了 ... -I {} cp {} ...,而不是尝试创建一个由每一行输入组成的大参数字符串并尝试将其传递给 cp, 它执行 cp 使用每行输入作为源操作数。

为了进一步解释,请考虑这种情况。我们有一个名为 test.txt 的文件,其中包含以下内容:

some_file.txt
another_file.txt
a_third_file.txt

现在,假设我们要编写一个命令来将所有这些文件复制到给定的目的地。如果我们简单地写...

cat test.txt | xargs cp /path/to/destination

...那么 cp 有效地看到的是:

cp some_file.txt another_file.txt a_third_file.txt

在这种形式下,它试图将 a_third_file.txt 视为目录并将前两个文件复制到其中(这就是为什么在您的情况下 cp 说第 150 条路径不是目录) . xargs -I {} 修复了:

cat test.txt | xargs -I {} cp {} ~/path/to/destination

现在,cp 不再只执行一次,而是 cp 执行了三次:

cp some_file.txt ~/path/to/destination
cp another_file.txt ~/path/to/destination
cp a_third_file.txt ~/path/to/destination

如果使用 cp 的 GNU 版本,它有一个 -t directory 选项来指定要复制给定的所有文件名的目标,而不是将其作为最后一个参数:

head -n 150 ../indexes/index.txt | xargs cp -t ~/path/to/destination/