连接文件的最快方法

fsp*_*rle 29 bash shell-script files cat

我有 10k+ 个文件,总共超过 20GB,我需要将它们连接成一个文件。

有没有比这更快的方法

cat input_file* >> out
Run Code Online (Sandbox Code Playgroud)

?

首选方式是 bash 命令,如果不是太慢,Python 也是可以接受的。

Gra*_*eme 30

不,猫肯定是做到这一点的最佳方式。既然已经有一个用 C 编写的程序,为什么要使用 python 呢?但是,如果xargs命令行长度超过ARG_MAX并且您需要多个cat. 使用 GNU 工具,这相当于您已经拥有的:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out
Run Code Online (Sandbox Code Playgroud)

  • @MarcvanLeeuwen,`xargs` 将尽可能调用 `cat`,这是避免 execve(2) 的 E2BIG 错误所必需的。 (3认同)

Sté*_*las 23

首先为输出文件分配空间可能会提高整体速度,因为系统不必为每次写入更新分配。

例如,如果在 Linux 上:

size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
  find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat 1<> out
Run Code Online (Sandbox Code Playgroud)

另一个好处是,如果没有足够的可用空间,则不会尝试复制。

如果打开btrfs,您可以创建copy --reflink=always第一个文件(这意味着没有数据复制,因此几乎是即时的),然后附加其余文件。如果有 10000 个文件,除非第一个文件非常大,否则可能不会有太大区别。

有一个 API 可以概括它来引用复制所有文件(BTRFS_IOC_CLONE_RANGE ioctl),但我找不到任何公开该 API 的实用程序,因此您必须使用 C(python或其他语言,只要它们可以调用任意ioctls) .

如果源文件稀疏或包含大量 NUL 字符序列,您可以使用(在 GNU 系统上)制作一个稀疏输出文件(节省时间和磁盘空间):

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out
Run Code Online (Sandbox Code Playgroud)

  • @grebneke,`&lt;&gt;` 是标准的 Bourne/POSIX 读+写重定向操作符。有关详细信息,请参阅您的 shell 手册或 [POSIX 规范](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_07)。`&lt;&gt;` 操作符的默认 `fd` 是 `0`(`&lt;&gt;` 是 `0&lt;&gt;` 的缩写,就像 `&lt;` 是 `0&lt;` 的缩写,`&gt;` 是 `1&gt; 的缩写`),因此您需要使用 `1` 来显式重定向标准输出。在这里,并不是说我们需要读+写(`O_RDWR`),而是我们不希望`O_TRUNC`(如`&gt;`)会释放我们刚刚分配的内容。 (5认同)