连接文件的最快方法


25

我有10k +个文件,总计超过20GB,我需要将它们串联成一个文件。

有没有比这更快的方法

cat input_file* >> out

首选方式是bash命令,即使不是相当慢,Python也是可以接受的。


更新了我的答案,find不对与Shell Glob相同的文件进行排序。
Graeme 2014年

5
由于时间将是99%的系统I / O,因此任何(所有)(合理的)解决方案在此处的速度都相同。
goldilocks 2014年


3
考虑将串联文件写入与要读取的磁盘不同的磁盘中。
2014年

1
如果out位于另一个磁盘上,它将更快。

Answers:


30

不,猫无疑是最好的方式。如果已经有一个用C语言编写的程序,为什么要使用python?但是,如果xargs命令行长度超过ARG_MAX并且需要多个,您可能要考虑使用cat。使用GNU工具,这等效于您已经拥有的工具:

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out

1
在这种情况下,您可以确保按顺序读取文件吗?
2014年

1
是的,因为的输出find通过传递sort。否则,文件将以任意顺序列出(由文件系统定义,可以是文件创建顺序)。
scai 2014年

@scai我很抱歉念错了,这种情况很明显
Kiwy 2014年

1
@Kiwy,我只能看到的一种情况是,如果环境中的语言环境设置不正确,那么排序的行为可能会与bashglob 不同。否则,我看不到任何情况xargscat表现不正常的情况。
Graeme 2014年

3
@MarcvanLeeuwen,xargscat在必要时调用以避免execve(2)的E2BIG错误。
斯特凡Chazelas

21

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

例如,如果在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

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

如果选中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

1
@XTian,不,应该是既不>也不>>,但1<>正如我所说写入文件。
斯特凡Chazelas

5
@grebneke <>是标准的Bourne / POSIX读+写重定向操作符。有关详细信息,请参见您的Shell手册或POSIX规范。缺省值fd0用于<>运算符的(<>是的缩写0<>,例如<是的缩写0<>简称1>),因此您需要1显式重定向stdout。在这里,我们不需要读+写(O_RDWR)太多了,但我们不希望O_TRUNC(如>)会取消分配刚分配的内容。
斯特凡Chazelas

1
@grebneke,unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22会给你一些。ksh93具有查找操作符BTW,您可以dd通过阅读或通过阅读来查找。
斯特凡Chazelas

1
@StephaneChazelas-非常感谢,感谢您的帮助和知识!
grebneke 2014年

1
我不相信会有很多情况fallocate抵消额外费用的开销find,尽管第二次会更快。btrfs当然会带来一些有趣的可能性。
Graeme 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.