对于这个问题中的所有内容,假设系统只有一个磁盘和文件系统。 (我们不会写入不同的分区、磁盘或文件系统)
我正在开发一个项目,该项目cat
将非常大的 .MTS 文件合并为一个巨大的 .MTS 文件。这需要读取每个小文件并将它们写入一个新的更大文件,然后删除小文件。对于这么大的文件,这需要很长时间。
我的理解-cp
需要更长的时间mv
,因为cp
读取文件并将其写入磁盘上的不同位置。mv
另一方面不复制或移动文件。mv
删除对该文件的引用并在新位置创建一个新引用。例如,mv /tmp/foo /tmp/bar
将文件保留在磁盘上,并删除指向/tmp/foo
磁盘上文件的引用,并添加指向/tmp/bar
磁盘上文件的新引用。
问题:
cat
就像cp
因为它将文件复制到新位置。对于如此大的文件,当我完成后不需要较小的文件,是否有类似的东西cat
使用mv
而不是cp
?
理论(我可能说错了)
文件分散存储在驱动器上已经很常见。例如,2GB 文件可能有几个较小的块存储在驱动器的不同部分。这样,当删除 5K 文件时,可以用 20MB 文件的一部分覆盖它。如果我们将 2GB 文件保留在原处并仅引用所有部分,那么似乎我们可以cat foo/* >> bar/bigfile.MTS; rm foo/*
在一小部分时间内实现相同的效果。
如果没有任何东西可以做到这一点并且这是一个坏主意,任何人都可以给我举个例子说明为什么吗?鼓励用分散的文件块弄乱磁盘是不是不好?
答案1
现有这样的工具的最大障碍是,除非连接的每个文件的大小(最后一个除外)完全可以被块大小整除(我对这里的正确术语有点不确定),否则你最终会得到最终文件中串联文件之间存在垃圾数据的“间隙”。
这是因为文件数据通常存储在文件系统上具有特定大小的块中,因此使用 32 字节块存储在文件系统上的 618 字节文件将占用 618 / 32 = 19.3125 个块,即 19 个完整块,大约额外块的 1/3。
假设您想组合这样的两个文件而不考虑我的障碍,您只需将“新文件”指向第一个文件的块,加上第二个文件的块,对吧?
使用这种简单的方法,您最终会得到一个包含 40 个块的文件,其中块 20 为 1/3 合理,2/3 为垃圾,块 21 开始第二个文件的数据。
对于某些文件格式,您可能能够对文件头进行一些巧妙的计算和操作,基本上告诉应用程序将使用该文件跳过垃圾部分,但这更像是一种创可贴解决方案,而不是正确的解决方案。
答案2
这是来自 stackoverflow 的类似问题https://stackoverflow.com/questions/5893531/fast-concatenate-multiple-files-on-linux
简单的答案是这样的——
只有保证所有文件(最后一个除外)的大小是文件系统块大小的倍数时,它才能起作用。
因为文件系统需要读取所有块直到文件末尾。