解决大型GZIPPED文件未压缩大小的最快方法


24

压缩文件后,有一种方法可以快速查询该文件,以说出未压缩文件的大小(不解压缩),尤其是在未压缩文件的大小> 4GB的情况下。

根据RFC https://tools.ietf.org/html/rfc1952#page-5,您可以查询文件的最后4个字节,但是如果未压缩的文件大于4GB,则该值仅代表uncompressed value modulo 2^32

也可以通过运行检索此值gunzip -l foo.gz,但是“未压缩”列仅包含uncompressed value modulo 2^32一次,大概是因为它如上所述读取了页脚。

我只是想知道是否有一种无需先解压缩即可获取未压缩文件大小的方法,这在压缩文件包含50GB +数据并且使用诸如 gzcat foo.gz | wc -c


编辑: 4GB限制已在OSX()随附mangzip实用程序页面中公开确认Apple 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必须比该社区中的许多用户年龄更大!
Celada's

2
gzip于1992年问世。如果周围有23岁的年轻人漫游,我会感到惊讶。我敢肯定有一些,但据我所知,中位年龄在30-35岁左右。
布拉奇利,2015年

2
可能是切换到xz没有此限制的好时机。GNU切换到xz
斯特凡Chazelas

@StéphaneChazelas有趣。不幸的是,我感兴趣的文件不在我的控制范围内(即,我们将其压缩了),但是看起来确实xz 可以“解决”此问题。
djhworld,2015年

Answers:


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字节的页脚,4字节的CRC和8字节(64位)的文件大小。但是,这将破坏与现有gzip的向后兼容性!
djhworld,2015年

我上面给出的解决方案不涉及初始压缩文件,即使我正在运行gzip;我只是gzip在压缩文件上运行,它不会重新压缩它们,只会验证它们。(该修补程序是一种快速而肮脏的概念验证,它需要进行一些其他更改才能使用gunzip。)
Stephen Kitt 2015年

@StephenKitt真有趣!更好/更恶劣的破解方法是将数据嵌入到FCOMMENT现场。这样,用户可以查询字节范围以检索该数据。就我而言,这将非常有用,特别是对于存储在Amazon S3中的项目
djhworld,2015年

0

如果你需要的文件的压缩文件或集的大小,最好的办法是使用tar -ztar -j代替gziptar包括未压缩的文件大小。使用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当然。但是要花费所有时间才能获得所有结果。因此,我有两个建议来记录文件大小。

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试图避免要做的事情。
depquid '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.