非圧縮サイズの大きなGZIPPEDファイルを処理する最速の方法


24

ファイルをgzipで圧縮すると、特に非圧縮ファイルのサイズが4 GBを超える場合に、非圧縮ファイルサイズが何であるかを(圧縮解除せずに)すばやく照会する方法があります。

RFC https://tools.ietf.org/html/rfc1952#page-5によると、ファイルの最後の4バイトを照会できますが、非圧縮ファイルが> 4GBの場合、値は単にuncompressed value modulo 2^32

この値はを実行して取得することもできますがgunzip -l foo.gzuncompressed value modulo 2^32上記のようにフッターを読み込んでいると考えられるため、「uncompressed」列には再び含まれています。

最初に解凍せずに非圧縮ファイルサイズを取得する方法があるかどうか疑問に思っていましたが、これはgzipされたファイルに50GB以上のデータが含まれ、次のような方法を使用して解凍するのに時間がかかる場合に特に便利です gzcat foo.gz | wc -c


編集: 4GBの制限は、OSXに含まれるユーティリティのmanページで公に認められていますgzipApple gzip 242

  BUGS
    According to RFC 1952, the recorded file size is stored in a 32-bit
    integer, therefore, it can not represent files larger than 4GB. This
    limitation also applies to -l option of gzip utility.

2
+1良い質問!答えはノーだと思います。ヘッダー形式は、そのようなファイルサイズが予想される前の時間に設計されたものです。それについて考えると、gzipこのコミュニティの多くのユーザーよりも年上でなければなりません!
セラダ

2
gzip1992年に出てきました。この辺りに23歳の人がたくさんいると驚くでしょう。確かにいくつかあると思いますが、年齢の中央値は30〜35歳であると言えます。
ブラッチリー

2
xzその制限のないものに切り替える良い機会かもしれません。GNUはに切り替えていxzます。
ステファンシャゼル

@StéphaneChazelas興味深い。残念ながら、興味のあるファイルは制御できません(つまり、圧縮されたファイルを受け取ります)が、確かにxz この問題を「解決」するように見えます。
-djhworld

回答:


11

最速の方法はgzip、冗長モードでのテストが解凍されたバイト数を出力するように変更することだと思います。私のシステムでは、7761108684バイトのファイルで、

% time gzip -tv test.gz
test.gz:     OK (7761108684 bytes)
gzip -tv test.gz  44.19s user 0.79s system 100% cpu 44.919 total

% time zcat test.gz| wc -c
7761108684
zcat test.gz  45.51s user 1.54s system 100% cpu 46.987 total
wc -c  0.09s user 1.46s system 3% cpu 46.987 total

gzip(1.6、Debianで利用可能)を変更するためのパッチは次のとおりです。

--- a/gzip.c
+++ b/gzip.c
@@ -61,6 +61,7 @@
 #include <stdbool.h>
 #include <sys/stat.h>
 #include <errno.h>
+#include <inttypes.h>

 #include "closein.h"
 #include "tailor.h"
@@ -694,7 +695,7 @@

     if (verbose) {
         if (test) {
-            fprintf(stderr, " OK\n");
+            fprintf(stderr, " OK (%jd bytes)\n", (intmax_t) bytes_out);

         } else if (!decompress) {
             display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
@@ -901,7 +902,7 @@
     /* Display statistics */
     if(verbose) {
         if (test) {
-            fprintf(stderr, " OK");
+            fprintf(stderr, " OK (%jd bytes)", (intmax_t) bytes_out);
         } else if (decompress) {
             display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
         } else {

内部で実際のデータを構築していますか、それとも-tすでに最適化されていますか?この改善は、出力時間を節約しただけのように見えるほど小さいものです。
frostschutz

はい、元のサイズを把握するためにすべてを解凍する必要があります...これは出力時間を節約するだけですが、保存できるのはそれだけだと思います。
スティーブンキット

興味深いことに、実際に機能させるにはコードを変更する必要があると考えていました。残念ながら、私のインスタンスでは、興味のあるファイルは実際には自分の管理下にはありません。外部からファイルを受け取っているので、そもそもそれらを圧縮することはできません。4GBを超えるファイルを完全にサポートする唯一の方法は、gzipにパッチを適用して12バイトのフッター、CRCに4バイト、ファイルサイズに8バイト(64ビット)を使用することだと思います。ただし、これは既存のgzipとの後方互換性を壊します!
djhworld

上記のソリューションでは、実行中であってもファイルを最初に圧縮する必要はありませんgzipgzip圧縮ファイルで実行するだけです。圧縮ファイルは再圧縮されず、検証されます。(このパッチは、迅速かつダーティな概念実証であり、使用するにはさらにいくつかの変更が必要gunzipです。)
Stephen Kitt

@StephenKittああ面白い!さらに良い/ダーティハックは、そのデータをFCOMMENTフィールドに埋め込むことです。これにより、ユーザーはバイト範囲を照会してそのデータを取得できます。これは私の場合、特にAmazon S3に保存されているアイテム
-djhworld

0

あなたはファイルの圧縮ファイルまたはセットのサイズが必要な場合は、あなたの最善の策は使用することがあるtar -ztar -jの代わりgzipとしてtar非圧縮ファイルのサイズが含まれています。lesspipeファイルのリストを覗くために使用:

aptitude install lesspipe
lesspipe <compressed file> | less

もしless使用するように設定されてlesspipe

less <compressed file>

ただし、非常に長い時間がかかる可能性があることに留意してください。ただし、システムは応答性を維持するため、解凍プロセスを強制終了できます。

別のアプローチは、圧縮率をログに記録し、代わりにその[text]ファイルをクエリすることです。

gzip --verbose file 2>&1 | tee file.gz.log
file:    64.5% -- replaced with file.gz

ただし、実際のファイルサイズを見つけるには計算が必要です。

を使用して同じことを行うこともできますtar。これは、実際には、たとえばファイルサイズまたは名前のみを取得するために解凍プロセス全体を実行することを防ぐため、大きなサイズのバックアップで行います。


2
すべてのファイルのリストを取得するために、tar.gzも完全に解凍する必要はありませんか?
frostschutz

確かにそうでなければなりません。これは、非圧縮ファイルサイズを取得する唯一の方法です。ではtar、あなたは、元のファイルサイズは、アーカイブに記録されています。zip一方で、私が違う振る舞いをするかどうかはわかりません。

1
その時点で、OPがwc -cコマンドを実行することもあります。
ブラッチリー

@Bratchleyもちろん。しかし、すべての結果を得るにはかなりの時間がかかります。したがって、ログファイルのサイズに関する2つの提案があります。

0

どう?

gzip -l file.gz|tail -n1|awk '{print $2}'

numfmt --to=iec $(gzip -l file.gz|tail -n1|awk '{print $2}')

1
OPで説明されているように、これは大きなファイルでは機能しません。
スティーブンキット

-2
gunzip -c $file | wc -c

これには長い時間がかかりますが、最終的なサイズはバイト単位で表示されます。


5
これはまさに、OPがやらなければならないことを避けようとしていることです。
16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.