为什么我不能将查找结果通过管道传输到 cp,但它可以使用 exec?
Why can't I pipe find results into cp, but it works using 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 不起作用。
我不使用 xargs,但我认为它应该像这样工作:
cp `find /path/to/encompassing/directory/ -d -name "*modified.tif"` Destination_Directory/
那就不用管了。
如果你写
find -name '*modified.tif' | xargs cp directory
那就和写一样了
cp directory 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
,您可以对 cp
使用 -t
选项,以便可以将要复制的文件附加到命令的末尾(需要GNU 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 {} +
确保尽可能少地调用 cp
。
xargs
将其标准输入中的每个单词作为 last 参数传递给 cp
,而不是第一个。因此,您正在尝试 运行 一系列命令
cp Destination_Directory/ foo
cp Destination_Directory/ bar
# etc
如果您使用的是 GNU cp
,您可以简单地通过使用 -t
选项来指定 Destination_Directory
是 目标 来解决这个问题],而不是来源。
... | xargs cp -t Destination_Directory
# cp -t Destination_Directory foo
# cp -t Destination_Directory bar
# etc
您可能能够使用xargs
中的-I
选项使其使用传入的文件名作为第一个参数:
... | xargs -I '{}' cp '{}' Destination_Directory
然而,这对 find
将产生的名称做了很多假设。 (没有前导或尾随空格,文件名中也没有换行符。)(就此而言,xargs
without -I
正在处理每个以空格分隔的 word 作为调用 cp
的单独参数。)通常,您不应尝试以编程方式使用 find
的输出。坚持使用它的 -exec
主节点。
您的代码
find /path/ -d -name "*modified.tif" -type f -exec cp {} Destination_Directory \;
是正确的方法。不涉及 shell,因此每个文件名都按原样 作为 作为第一个参数传递给 cp
.
我正在使用 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 不起作用。
我不使用 xargs,但我认为它应该像这样工作:
cp `find /path/to/encompassing/directory/ -d -name "*modified.tif"` Destination_Directory/
那就不用管了。
如果你写
find -name '*modified.tif' | xargs cp directory
那就和写一样了
cp directory 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
,您可以对 cp
使用 -t
选项,以便可以将要复制的文件附加到命令的末尾(需要GNU 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 {} +
确保尽可能少地调用 cp
。
xargs
将其标准输入中的每个单词作为 last 参数传递给 cp
,而不是第一个。因此,您正在尝试 运行 一系列命令
cp Destination_Directory/ foo
cp Destination_Directory/ bar
# etc
如果您使用的是 GNU cp
,您可以简单地通过使用 -t
选项来指定 Destination_Directory
是 目标 来解决这个问题],而不是来源。
... | xargs cp -t Destination_Directory
# cp -t Destination_Directory foo
# cp -t Destination_Directory bar
# etc
您可能能够使用xargs
中的-I
选项使其使用传入的文件名作为第一个参数:
... | xargs -I '{}' cp '{}' Destination_Directory
然而,这对 find
将产生的名称做了很多假设。 (没有前导或尾随空格,文件名中也没有换行符。)(就此而言,xargs
without -I
正在处理每个以空格分隔的 word 作为调用 cp
的单独参数。)通常,您不应尝试以编程方式使用 find
的输出。坚持使用它的 -exec
主节点。
您的代码
find /path/ -d -name "*modified.tif" -type f -exec cp {} Destination_Directory \;
是正确的方法。不涉及 shell,因此每个文件名都按原样 作为 作为第一个参数传递给 cp
.