评论

评论

假设我有两个文件 A 和 B,每个文件大小为 50 GB,还有大约 100 个大小可以忽略不计的其他文件。我只有 120 GB 的磁盘空间(其中 100 GB 被文件 A 和 B 占用)。我想创建一个包含文件 A 和 B 以及其他 100 个文件的 tar 存档。是否可以在剩余磁盘空间少于 20 GB 的情况下实现此目的?

tar 存档将上传到长期云存储解决方案(例如 Amazon S3 Glacier Deep Archive、Google Cloud Archive Storage 等)。

答案1

tar 存档将上传到长期云存储解决方案(例如 Amazon S3 Glacier Deep Archive、Google Cloud Archive Storage 等)。

啊!所以你真的永远不需要磁盘上的 tar 存档!

相反,您可以即时创建 tar 存档,同时将其上传到 amazon S3 或其他地方。另外,你真的想要压缩,因为你是按容量付费的。

解决方案应该非常简单:

tar c fileA fileB | aws s3 cp s3://mybucket/backup.tar -
    : :     :     :           :                        :
    : :     :     :           :                        \- read data from stdin
    : :     :     :           \- How to call the object
    : :     :     \- unix pipe: the stdout of the
    : :     :        tar command becoms the stdin
    : :     :        of the aws command.
    : \-----\- files to be compressed
    \--compression command

就个人而言,特别是当您说您有数千个非常小的文件时,tar格式的开销变得非常大。我建议使用

tar c --zstd file1 file2 … file1000 | aws s3 cp s3://mybucket/backup.tar.zst -

即时压缩数据。它可以节省您的上传时间和云主机上的付费空间,并且通常是在这里做的正确的事情。

答案2

评论

这个解决方案是不合适的,因为询问者后来指出它既不是关于两个大文件,也不是关于在本地实际存储 tar 存档。但看到它仍然解决了问题的原始标题,我想我会把它留给后代。

回答

因此,问题是:在读完文件之前,您无法“释放”文件所使用的空间;因此,将文件放入存档的标准方法tar不起作用,因为这基本上是:

  • 读取第一个文件的属性(名称、长度、所有者等)
  • 将包含该信息的标头写入 .tar 文件的位置 0;该标头的长度为 512 字节
  • 复制标头后第一个文件的内容,用零填充到下一个 512 字节的倍数(用零填充)
  • 读取第二个文件的属性
  • 在第一个文件末尾写入第二个文件的标头
  • 复制第二个文件的内容,与 512 B 的下一个倍数对齐
  • 最后,删除这两个文件

正如您所看到的,tar 档案可以非常简单地连接起来。遗憾的是,您甚至无法将一个文件的内容复制到 tar 存档,然后删除该文件,然后存档下一个文件,因为在第一个完成写入之前您将耗尽空间(并且没有 POSIX 方法来截断该文件)开始您已经阅读过的文件的一部分)。因此,卡米尔上述评论中的方法行不通。

所以,只要你的文件系统不支持重新链接部分文件,这是不可能的。 (目前,2021 年 6 月,唯一支持该功能的 Linux 文件系统是 XFS 和 btrfs。但是,您必须自己编写该软件;您需要研究一下man ioctl_ficlonerange,它允许您共享原始文件所使用的内存文件和存档文件。)


然而,拥有 100 GB 的 tar 文件本身听起来毫无用处。你打算用它做什么?您可以将其复制到其他设备或通过网络,在这种情况下您绝不必须在您自己的驱动器上!

您只需即时创建该 tar 存档,而不是首先在硬盘驱动器上生成它,然后复制它。tar不关心它是否将结果写入文件、块设备(tar时间氩气韭菜,无论如何!)或网络套接字。

因此,看到你想做的事情是不可能的可能会令人沮丧 - 但我认为你可能正在解决一个非问题。

¹ 除非您的文件都位于同一个 XFS 或 btrfs 文件系统上,并且您知道 anioctl是什么并且愿意编写代码

相关内容