![如何在 Linux 上就地压缩文件而不使用额外的磁盘空间?](https://linux22.com/image/1301549/%E5%A6%82%E4%BD%95%E5%9C%A8%20Linux%20%E4%B8%8A%E5%B0%B1%E5%9C%B0%E5%8E%8B%E7%BC%A9%E6%96%87%E4%BB%B6%E8%80%8C%E4%B8%8D%E4%BD%BF%E7%94%A8%E9%A2%9D%E5%A4%96%E7%9A%84%E7%A3%81%E7%9B%98%E7%A9%BA%E9%97%B4%EF%BC%9F.png)
我有一个 100GB 的驱动器,里面有一个 95GB 的文件。我需要释放驱动器上的一些空间(目前无法将文件从驱动器中转移出去)。使用gzip
或bz2
或其他方式可以很好地压缩文件,但所有这些程序都会将压缩文件写入单独的文件。我没有足够的可用空间来执行此操作。
有没有办法使用标准压缩工具或其他 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