如何用很少的备用磁盘空间连接两个巨大的文件?

时间:2008-11-14 16:43:03

标签: filesystems concatenation large-files

假设您有两个要连接在一起的大文件(几GB),但是您的备用磁盘空间非常少(假设有几百MB)。也就是说,给定file1file2,您希望得到一个文件,这是将file1file2连接在一起的结果,并且删除原始文件。

你不能做明显的cat file2 >> file1; rm file2,因为在这两个操作之间,你的磁盘空间不足。

欢迎使用免费或非免费工具在任何和所有平台上使用解决方案;这是我前几天下载Linux ISO时想到的一个假设性问题,由于无线打嗝,下载中途中断。

15 个答案:

答案 0 :(得分:15)

花时间计算出涉及磁盘扇区改组和文件链操作的巧妙解决方案:2-4小时

获取/编写软件以进行就地复制和截断的时间:2-20小时

倍中位数$ 50 /小时程序员费率:$ 400- $ 1200

1TB USB驱动器的成本:100美元至200美元

理解短语“机会成本”的能力:无价的

答案 1 :(得分:8)

我认为困难在于确定如何从原始文件中恢复空间。

我认为以下内容可能有效:

  1. 分配一个稀疏文件 合并尺寸。
  2. 将100Mb从第二个文件的末尾复制到新文件的末尾。
  3. 截断第二个文件末尾的100Mb
  4. 循环2& 3直到您完成第二个文件(将2.修改为目标文件中的正确位置)。
  5. 2& 3& 4,但第一个文件。
  6. 这一切都依赖于稀疏文件支持和文件截断立即释放空间。

    如果您确实想要这样做,那么您应该调查dd命令。哪个可以进行复制步骤

    另一个回答中的某个人给出了一个不需要稀疏文件的简洁解决方案,但是复制了两次文件:

    1. 将100Mb块从文件2的末尾复制到新文件3,以相反的顺序结束。在你去的时候截断文件2.
    2. 将文件3末尾的100Mb块复制到文件1中,最后按原始顺序复制块,位于文件1的末尾。随后截断文件3.

答案 2 :(得分:7)

这比我的first answer略有改进。

如果您有100MB可用空间,请从第二个文件复制最后100MB并创建第​​三个文件。截断第二个文件,使其现在缩小100MB。重复此过程,直到第二个文件完全分解为单个100MB块。

现在,每个100MB文件都可以附加到第一个文件中,一次一个。

答案 3 :(得分:4)

有了这些限制,我希望你需要篡改文件系统;直接编辑文件大小和分配块。

换句话说,忘记改组文件内容的任何块,只需编辑有关这些文件的信息。

答案 4 :(得分:2)

如果文件是高度可压缩的(即日志):

gzip file1

gzip file2

zcat file1 file2 | gzip > file3

rm file1

rm file2

gunzip file3

答案 5 :(得分:1)

冒着轻浮的风险,您是否考虑过选择更大的磁盘?它可能会更快......

答案 6 :(得分:1)

效率不高,但我认为可以做到。

以附加模式打开第一个文件,并将第二个文件中的块复制到该文件,直到磁盘快满为止。对于第二个文件的其余部分,通过随机访问I / O将块从您停止的位置复制到文件的开头。复制完最后一个块后截断文件。重复直到完成。

答案 7 :(得分:1)

好的,对于理论娱乐,只有当你保证不浪费你的时间实际做到这一点:

  • 文件存储在磁盘上
  • 这些作品以链式链接

所以你可以通过以下方式连接文件:

  • 将第一个文件的最后一部分链接到最后一个文件的第一部分
  • 更改第一个文件的目录条目以更改最后一个文件和文件大小
  • 删除最后一个文件的目录条目
  • 清理第一个文件的文件结束标记(如果有)
  • 请注意,如果第一个文件的最后一段仅部分填充,则必须将数据“向上”复制到最后一个文件的段中,以避免在文件中间出现垃圾[感谢@Wedge!] < / LI>

这将是最佳效率:最小化更改,最小复制,无需备用磁盘空间。

现在去买一个USB驱动器; - )

答案 8 :(得分:1)

显然,经济上的答案是购买更多的存储空间,假设这是一个可能的答案。但它可能不是 - 嵌入式系统无法连接更多存储设备,甚至无法访问设备本身 - 例如,飞行中的太空探测器。

如果您有稀疏文件系统,以前提供的基于稀疏文件系统的答案是好的(除了出现问题之外的破坏性质!)。如果你不这样做怎么办?

从文件2的末尾开始复制块到目标文件的开头,然后将它们反转。在每个块之后,您将源文件截断为未复制的长度。重复文件#1。

此时目标文件向后包含所有数据,源文件消失。

从tart和目标文件的末尾读取一个块,将它们反转并将它们写入另一个来自的位置。按照你的方式向前翻转。

完成后,目标文件是源文件的串联。不需要稀疏文件系统,不需要处理所需的文件系统。这可以在零字节空闲时执行,因为数据可以保存在存储器中。

答案 9 :(得分:0)

两个想法:

如果你有足够的物理RAM,你实际上可以将第二个文件完全读入内存,删除它,然后以追加模式将其写入第一个文件。当然如果你在删除之后但在完成写入之前失去了权力,你就会丢失部分第二个文件。

暂时减少操作系统功能使用的磁盘空间(例如虚拟内存,“回收站”或类似内容)。可能只在Windows上使用。

答案 10 :(得分:0)

我怀疑这是对这个问题的直接回答。您可以将此视为解决问题的替代方法。

我认为可以将第二个文件视为第一个文件的第2部分。通常在zip应用程序中,我们会看到一个巨大的文件被分成多个部分。如果您打开第一部分,应用程序将自动考虑其他部分进行进一步处理。

我们可以在这里模拟同样的事情。正如@edg所指出的,修补文件系统将是一种方式。

答案 11 :(得分:0)

你可以这样做:

head file2 --bytes=1024 >> file1 && tail --bytes=+1024 file2 >file2 

你可以根据你有多少额外的磁盘空间来增加1024,然后重复这个,直到所有的字节都被移动。

这可能是最快的方式(就开发时间而言)

答案 12 :(得分:0)

您可以通过压缩整个文件系统来获得空间。我相信NTFS支持这一点,我相信有一些* nix文件系统可以支持它。它还有一个好处,就是在复制文件后,你仍然会有比剩下更多的磁盘空间。

答案 13 :(得分:0)

好的,稍微改变一下这个问题。磁盘上还有其他你不需要的东西,但你不知道它是什么或它在哪里。如果你能找到它,你可以删除它,然后你可能有足够的额外空间。

为了找到这些“肿瘤”,无论是几个大肿瘤,还是许多小肿瘤,我都会使用一些小样本程序。从目录(或根目录)的顶部开始,它进行两次传递。在第1遍中,它遍历目录树,将所有文件的大小相加以获得总共N个字节。在第2遍中,它再次遍历目录树,假装它正在读取每个文件。每次传递N / 20字节时,它都会打印出目录路径和它正在“读取”的文件名。因此,最终结果是20个深度的路径名样本均匀地分布在目录下的所有字节中。

然后只看那些显示你不需要的东西的清单,然后把它吹走。

(这是我用于性能优化的采样方法的空间等效。)

答案 14 :(得分:-1)