如何在不使用额外磁盘空间的情况下在 Linux 上就地压缩文件?

Lee*_*Lee 25 linux compression

我有一个 100GB 的驱动器,里面有一个 95GB 的文件。我需要释放驱动器上的一些空间(现在不能将文件从驱动器传输出来)。该文件将与压缩以及gzipbz2或什么,但所有这些程序写入的压缩文件到一个单独的文件。我没有足够的可用空间。

有没有办法使用标准压缩工具或其他 Unix 实用程序来压缩文件而不使用任何额外的磁盘空间(或至少是最少的额外磁盘空间)?我正在想象一次压缩文件的一部分并将结果直接写在文件上的东西。我意识到这会有风险,因为如果压缩中断,文件就会损坏,但我认为我别无选择。

use*_*307 15

这是 bash one-liner 概念的证明,但它应该可以帮助您入门。使用风险自负。

truncate -s `gzip -c file | dd of=file conv=notrunc 2>&1 | sed -n '$ s/ .*$// p'` file
mv file file.gz
Run Code Online (Sandbox Code Playgroud)

这是通过将 gz 数据管道传输到 dd 进程,该进程将其写回同一个文件来实现的。完成后,文件将被截断为 gz 输出的大小。

这假设 dd 输出的最后一行匹配:

已复制 4307 字节 (4.3 kB),2.5855e-05 秒,167 MB/秒

其中第一个字段是写入的整数字节。这是文件需要截断的大小。我不是 100% 确定输出格式总是相同的。

  • 是的。所以 conv=notrunc 是必要的。 (3认同)

小智 10

这不是这么多,gzipbzip2覆盖原来的。相反,他们将压缩数据作为新文件写入磁盘,如果该操作成功,他们将取消原始未压缩文件的链接。

如果您有足够的 RAM,您可以编写一个脚本来临时压缩文件tmpfs系统中的文件,然后删除磁盘上的原始文件并将其替换为压缩版本。也许是这样的:

# some distributions mount /dev/shm as tmpfs; replace with bzip2 if you prefer
if gzip -q9c /full/disk/somefile > /dev/shm/somefile.gz
then
    rm -f /full/disk/somefile && mv -i /dev/shm/somefile.gz /full/disk
fi
Run Code Online (Sandbox Code Playgroud)

请注意您的内存使用情况,因为tmpfs它本质上是一个 RAM 磁盘。一个大的输出文件很容易使系统饿死并给你带来其他问题。


Ign*_*ams 4

由于您给出的原因,没有任何工具可以以这种方式工作。很少有人愿意编写一个故意实施危险行为的工具。

  • 但您可以从文件的*末尾*删除数据。原则上是可以做到的。您可以从文件末尾切下数据以放入单独的文件中,同时截断原始文件。然后,您按正向顺序压缩文件,并在压缩时删除它们。实施起来会很痛苦,如果出了什么问题,你就会完蛋。但这是可能的。 (2认同)