为什么我无法将找到的结果通过管道传输到cp,但是使用exec可以正常工作?

时间:2018-11-09 15:08:43

标签: bash find exec

我正在使用find列出具有特定扩展名的多个目录中的文件。我尝试过

find /path/to/encompassing/directory/ -d -name "*modified.tif" | xargs  cp Destination_Directory/ 

但是没有用。使用

find /path/ -d -name "*modified.tif" -type f -exec cp {} Destination_Directory \;

有效,但我不明白为什么xargs无法正常工作。

3 个答案:

答案 0 :(得分:2)

如果你写

find -name '*modified.tif' | xargs cp directory

那和写作一样

cp directory filename file1modified.tif file2modified.tif

(或匹配的任何文件名),这是错误的方法,因为默认情况下xargs会附加参数。

find -name '*modified.tif' -exec cp {} directory \;

相同
cp file1modified.tif directory
cp file2modified.tif directory

这就是你想要的。

您可以使用xargs通过使用

xargs -I{} cp {} directory

指定要在命令中使用参数的位置,但这意味着一次只能复制一个文件(因为-I意味着-L1)。

为避免每个文件调用一次cp,可以对-t使用cp选项,这样可以将要复制的文件附加到命令的末尾(需要GNU { {1}}):

cp

等效于

find -name '*modified.tif' | xargs cp -t directory

或者更好,要注意文件名中的空格,

cp -t directory file1modified.tif file2modified.tif

或者,不带find -name '*modified.tif' -print0 | xargs -0 cp -t directory

xargs

其中find -name '*modified.tif' -exec cp -t directory {} + 确保尽可能少地调用-exec {} +

答案 1 :(得分:1)

cp将来自其标准输入的每个单词作为 last 参数传递给xargs,而不是第一个。结果,您正在尝试运行一系列命令

cp

如果您使用的是GNU cp Destination_Directory/ foo cp Destination_Directory/ bar # etc ,则可以通过使用cp选项指定-t target 而不是来源。

Destination_Directory

可能可以使用... | xargs cp -t Destination_Directory # cp -t Destination_Directory foo # cp -t Destination_Directory bar # etc 中的-I选项,使其使用传入文件名作为第一个参数:

xargs

但是,这将对... | xargs -I '{}' cp '{}' Destination_Directory 的名称产生很多假设。 (没有前导或尾随空格,文件名中没有换行符。)(因此,find xargs对待每个以空格分隔的 word < / em>作为输入来单独调用-I。)通常,您不应该尝试以编程方式使用cp的输出。坚持使用其find主数据库。

您的代码

-exec

是正确的方法。不涉及任何外壳程序,因此每个文件名均按原样传递 作为find /path/ -d -name "*modified.tif" -type f -exec cp {} Destination_Directory \; 的第一个参数。

答案 2 :(得分:-1)

我不使用xargs,但我认为它应该像这样工作:

cp `find  /path/to/encompassing/directory/ -d  -name "*modified.tif"` Destination_Directory/

那么就不需要管道了。