我有一个用 gzip 压缩的大文件 (420 GB),我想解压缩它,但我的硬盘没有空间来存储整个压缩文件及其内容。
有没有办法在“删除时”解压缩它?
如果有帮助, gzip -l 说里面只有一个文件(这是一个 tar 文件,我也必须以某种方式分开)
提前致谢!
有没有办法在“删除时”解压缩它?
这就是你所要求的。但这可能不是您真正想要的。使用风险自负。
如果 420GB 文件存储在具有稀疏文件和打孔支持(例如ext4
,xfs
,但不支持 )的文件系统上ntfs
,则可以使用 读取文件并释放读取块fallocate --punch-hole
。但是,如果该过程因任何原因被取消,则可能无法恢复,因为剩下的只是一个半删除、半解压缩的文件。不要在没有先制作另一个源文件副本的情况下尝试它。
非常粗略的概念证明:
# dd if=/dev/urandom bs=1M count=6000 | pigz --fast > urandom.img.gz
6000+0 records in
6000+0 records out
6291456000 bytes (6.3 GB, 5.9 GiB) copied, 52.2806 s, 120 MB/s
# df -h urandom.img.gz
Filesystem Size Used Avail Use% Mounted on
tmpfs 7.9G 6.0G 2.0G 76% /dev/shm
Run Code Online (Sandbox Code Playgroud)
urandom.img.gz
文件占用了76%的可用空间,所以不能直接解压。管道未压缩的结果,md5sum
以便我们稍后验证:
# gunzip < urandom.img.gz | md5sum
bc5ed6284fd2d2161296363edaea5a6d -
Run Code Online (Sandbox Code Playgroud)
打孔时解压缩:(这是非常粗糙的,没有任何错误检查)
total=$(stat --format='%s' urandom.img.gz) # bytes
total=$((1+$total/1024/1024)) # MiB
for ((offset=0; offset < $total; offset++))
do
# read block
dd bs=1M skip=$offset count=1 if=urandom.img.gz 2> /dev/null
# delete (punch-hole) blocks we read
fallocate --punch-hole --offset="$offset"MiB --length=1MiB urandom.img.gz
done | gunzip > urandom.img
Run Code Online (Sandbox Code Playgroud)
结果:
# ls -alh *
-rw-r--r-- 1 root root 5.9G Jan 31 15:14 urandom.img
-rw-r--r-- 1 root root 5.9G Jan 31 15:14 urandom.img.gz
# du -hcs *
5.9G urandom.img
0 urandom.img.gz
5.9G total
# md5sum urandom.img
bc5ed6284fd2d2161296363edaea5a6d urandom.img
Run Code Online (Sandbox Code Playgroud)
校验和匹配,源文件的大小从 6GB 减少到 0,而它在原地解压缩。
但是有很多事情可能会出错......最好根本不要这样做,或者如果你真的必须这样做,至少使用一个可以进行更明智的错误检查的程序。上面的循环根本不能保证数据在被删除之前被读取和处理。如果dd
或gunzip
出于任何原因返回错误,fallocate
仍然很乐意将其扔掉……因此,如果您必须使用这种方法,最好编写一个更明智的read-and-eat
程序。