gzipファイルの内部解凍

gzipファイルの内部解凍

gzipで圧縮された大容量ファイル(420 GB)があり、解凍したいのですが、ハードドライブに完全な圧縮ファイルとその内容を保存するスペースがありません。

「削除中に」解凍する方法はありますか?

役に立つなら、gzip -lは内部にファイルが1つしかないと言います(tarファイルなので、何とか分離する必要があります)。

よろしくお願いします!

ベストアンサー1

「削除中に」解凍する方法はありますか?

それがあなたが求めるすべてです。しかし、これはあなたが本当に欲しいものではないかもしれません。自分の責任で使用してください。

420GBファイルがスパースファイルとホールパンチングをサポートするファイルシステムに保存されている場合(たとえばext4xfsサポートされていない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

urandom.img.gzファイルは空き容量の76%を占めるため、直接解凍することはできません。md5sum後で確認できるように、圧縮されていない結果を私たちにパイプしてください。

# gunzip < urandom.img.gz | md5sum
bc5ed6284fd2d2161296363edaea5a6d  -

パンチング中に解凍:(非常に粗雑であり、エラーチェックはありません。)

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

結果:

# 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

チェックサムが一致し、解凍すると、ソースファイルのサイズが6 GBから0に減少します。

しかし、間違っている可能性がたくさんあります...まったくやらない方が良いです。必要に応じて、少なくともより強力なエラーチェックを実行するプログラムを使用してください。上記のループは、データが削除される前に読み取られ処理されたことをまったく保証しません。dd何らかのgunzip理由でエラーが返された場合は、fallocateそれを気にします。したがって、このアプローチを使用する必要がある場合は、より健全なread-and-eatプログラムを書くことをお勧めします。

おすすめ記事