【问题标题】:Why can't I pipe find results into cp, but it works using exec?为什么我不能通过管道将 find 结果输入 cp,但它可以使用 exec?
【发布时间】:2018-11-09 15:08:42
【问题描述】:

我正在使用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 无效。

【问题讨论】:

  • 您是否要复制文件或目录?不清楚。
  • 我正在尝试复制目录但只包含特定文件。
  • 您是否编辑了问题并意外删除了部分问题?
  • 第二个命令中的- name(有空格)是不是错字?
  • 是的,这是一个错字,抱歉。但没有什么是错字。现在 exec 标志起作用了,我意识到我需要复制保留目录结构的文件。我正在尝试使用同上而不是 cp。

标签: bash find exec


【解决方案1】:

如果你写

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

【讨论】:

    【解决方案2】:

    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 的第一个参数传递。

    【讨论】:

    • xargs 应该能够使用我想象的以下内容处理带有空格或换行符的文件名/目录:... -print0 | xargs -0I{} cp {} dest
    • 可以,但-print0-0 都不是标准的。几乎没有理由使用xargs 代替-exec。 (我意识到我使用cp -t 的建议也是非标准的,并且仍然 不适用于find 的所有可能输出,但它解决了乱序的主要问题cp 的参数。)
    【解决方案3】:

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

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

    那么就不需要管道了。

    【讨论】:

      猜你喜欢
      • 2014-12-01
      • 2013-12-16
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 2014-04-18
      • 2018-04-21
      • 1970-01-01
      相关资源
      最近更新 更多