使用ln整合数千个文件

时间:2017-05-04 18:52:52

标签: bash

我正在通过终端使用Bash命令在Mac计算机上工作。

我有~200个编号为0-200的目录。每个目录包含以.fast5结尾的5,000个单独文件。我试图找出将200个目录组中的所有文件合并到一个名为Consolidatedfiles的目录中的最简单方法。

我一直在尝试不同的方法,但没有一种方法有效。以下命令是我认为最接近的命令。

find ./* -iname "*fast.5" | xargs -I {} ln ./Consolidatedfiles {}

但是我搞乱了ln命令?我有{0}使用findxargs与其他命令配对的经验。

感谢您的帮助!

1 个答案:

答案 0 :(得分:5)

以下是最有效的解决方案,用于创建指向单个目标目录中所有文件的硬链接 [1] ,假设您可以使用 GNU ln 哪个macOS不附带(但您可以通过{安装它) {3}}):

find ./* -iname "*fast.5" -exec ln -t ./Consolidatedfiles/ {} +

macOS 允许使用xargs (特定于BSD)的高效 -J解决方案,该解决方案允许定义扩展为(通常)的占位符所有参数,与-0find -print0结合使用,可以有力地传递文件名:

find ./* -iname "*fast.5" -print0 | xargs -0 -J {} ln {} ./Consolidatedfiles/

POSIX兼容解决方案 慢得多,因为它会为每个文件调用ln

find ./* -iname "*fast.5" -exec ln {} ./Consolidatedfiles/ \;

请注意 find的{​​{1}}如何内置-exec,只有更强大且效率更高(因为没有管道和单独的需要xargs个过程):

  • xargs就像管道find ... -exec ... {} +

    • (通常)所有参数(尽可能多地适用于单个命令行,使用尽可能少的整体调用)立即传递 ,总是在特定命令的 end

    • 请注意,| xargs ... 必须{}之前的最后一个参数,这意味着文件名只能在结尾传递命令行。

      • 这就是上面需要 GNU +的原因,因为只有它 - 作为Homebrew的扩展 - 允许在 >文件操作数列表,ln
  • -t <dir>就像管道find ... -exec ... {} ... \;

    • | xargs -I {} ... {} ...指示的位置,为每个文件调用一次目标命令。
  • 使用{}也比-exec健壮,因为文件名总是正确传递,不关心带有空格,引号或嵌入的文件名换行。

    • 相比之下,xargs默认情况下将输入流按空格分隔为参数,并且仅使用符合POSIX的选项,不能保证所有参数都正确传递;然而,将xargsfind -print0结合起来非常有效,并且Linux(GNU实用程序)和macOS / BSD都支持这两种非标准选项。 谢谢,POSIX spec.

至于您尝试的内容

您的 xargs -0操作数顺序错误; ln语法为:

ln

所以你应该使用ln <original> <link>

通过该更正,您的命令应该可以正常工作,但出于效率的原因,最好使用基于ln {} ./Consolidatedfiles/的命令。

[1] 链接(与使用-exec创建的符号链接相对)很少使用,但它们对于安全移动文件分为两个阶段:硬链接指向磁盘上与原始文件完全相同的数据(事实上,即使原始文件是硬链接),所以一旦你确定了在目标位置正确创建了硬链接,您可以安全地删除原始文件(其内容不会丢失,因为新的硬链接仍然指向它们)。