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

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

我有一个 100GB 的驱动器,里面有一个 95GB 的文件。我需要释放驱动器上的一些空间(目前无法将文件从驱动器中转移出去)。使用gzipbz2或其他方式可以很好地压缩文件,但所有这些程序都会将压缩文件写入单独的文件。我没有足够的可用空间来执行此操作。

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

答案1

这是概念验证的 bash 单行代码,但它应该可以帮助您入门。使用时请自担风险。

truncate -s `gzip -c file | dd of=file conv=notrunc 2>&1 | sed -n '$ s/ .*$// p'` file
mv file file.gz

其工作原理是将 gz 数据传送到 dd 进程,然后将其写回到同一个文件。完成后,文件将被截断为 gz 输出的大小。

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

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

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

答案2

这并不是说要gzip覆盖bzip2原始文件。相反,它们会将压缩数据作为新文件写入磁盘,如果该操作成功,它们会取消链接原始的未压缩文件。

如果您有足够的 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

只需注意内存使用情况,因为tmpfs它本质上是一个 RAM 磁盘。较大的输出文件很容易导致系统资源不足并给您带来其他问题。

答案3

没有任何工具可以这样工作,原因正如你所说。很少有人愿意编写一个故意实施冒险行为的工具。

答案4

如果每个文件都适合内存,则可以使用海绵

gzip -c somefile | sponge somefile

相关内容