84

我正在寻找 DEFLATE 算法的命令行包装器。

我有一个使用 DEFLATE 压缩的文件(git blob),我想解压缩它。gzip 命令似乎没有直接使用 DEFLATE 算法而不是 gzip 格式的选项。

理想情况下,我正在寻找可以做到这一点的标准 Unix/Linux 工具。

编辑:这是我尝试使用 gzip 解决我的问题时得到的输出:

$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip

gzip: stdin: not in gzip format
4

21 回答 21

53

类似以下内容将打印原始内容,包括“$type $length\0”标头:

perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' \
     < .git/objects/27/de0a1dd5a89a94990618632967a1c86a82d577
于 2010-07-06T10:17:37.033 回答
49

您可以使用 OpenSSL 命令行工具执行此操作:

openssl zlib -d < $IN > $OUT

不幸的是,至少在 Ubuntu 上,该zlib子命令在默认构建配置 ( --no-zlib --no-zlib-dynamic) 中被禁用,因此您需要openssl从源代码编译才能使用它。但例如,它在 Arch 上默认启用。

编辑:似乎zlibArch 也不再支持该命令。这个答案可能不再有用了:(

于 2013-12-20T22:09:30.220 回答
39

pythonic单线:

$> python -c "import zlib,sys;print \
           repr(zlib.decompress(sys.stdin.read()))" < $IN
于 2011-11-30T12:34:39.423 回答
29

更新: Mark Adler 指出 git blob 不是原始的 DEFLATE 流,而是 zlib 流。这些可以通过该pigz工具解压缩,该工具预打包在多个 Linux 发行版中:

$ cat foo.txt 
file foo.txt!

$ git ls-files -s foo.txt
100644 7a79fc625cac65001fb127f468847ab93b5f8b19 0   foo.txt

$ pigz -d < .git/objects/7a/79fc625cac65001fb127f468847ab93b5f8b19 
blob 14file foo.txt!

由 kriegaex 编辑: Windows 用户的 Git Bash 会注意到pigz默认不可用。您可以在此处找到预编译的 32/64 位版本。我尝试了 64 位版本,它运行良好。例如,您可以将pigz.exe直接复制到c:\Program Files\Git\usr\bin以将其放在路径上。


我原来的答案,出于历史原因保留:

如果我理解Marc van Kempen 提到的维基百科文章puff.c中的提示,您可以直接使用from zlib

这是一个小例子:

#include <assert.h>
#include <string.h>
#include "puff.h"

int main( int argc, char **argv ) {
    unsigned char dest[ 5 ];
    unsigned long destlen = 4;
    const unsigned char *source = "\x4B\x2C\x4E\x49\x03\x00";
    unsigned long sourcelen = 6;    
    assert( puff( dest, &destlen, source, &sourcelen ) == 0 );
    dest[ 4 ] = '\0';
    assert( strcmp( dest, "asdf" ) == 0 );
}
于 2010-07-05T10:08:21.013 回答
28

您可以使用 zlib-flate,如下所示:

cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 \
    | zlib-flate -uncompress; echo

qpdf - tools for and transforming and inspecting PDF files默认情况下它在我的机器上,但如果您需要安装它,它是其中的一部分。

echo在命令的末尾弹出了一个,因为这样更容易阅读输出。

于 2013-10-09T14:51:15.883 回答
24

尝试以下命令:

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip

不需要外部工具。

资料来源:如何在 UNIX 中解压缩 zlib 数据?在 unix SE

于 2015-02-26T21:39:16.253 回答
14

这是一个 Ruby 单线器(首先 cd .git/ 并标识任何对象的路径):

ruby -rzlib -e 'print Zlib::Inflate.new.inflate(STDIN.read)' < ./74/c757240ec596063af8cd273ebd9f67073e1208
于 2011-12-28T21:13:12.987 回答
12

我厌倦了没有一个好的解决方案,所以我在 NPM 上放了一些东西:

https://github.com/jezell/zlibber

现在可以通过管道来充气/放气命令。

于 2013-08-04T02:29:26.943 回答
9

这是在 Python 中打开提交对象的示例:

$ git show
commit 0972d7651ff85bedf464fba868c2ef434543916a
# all the junk in my commit...
$ python
>>> import zlib
>>> file = open(".git/objects/09/72d7651ff85bedf464fba868c2ef434543916a")
>>> data = file.read()
>>> print data
# binary garbage
>>> unzipped_data = zlib.decompress(data)
>>> print unzipped_data
# all the junk in my commit!

您将看到的内容几乎与“git cat-file -p [hash]”的输出相同,只是该命令不打印标题(“提交”后跟内容大小和空字节)。

于 2011-06-30T18:01:12.217 回答
8

git 对象由zlib而不是压缩gzip,因此要么使用zlib解压缩它,要么使用 git 命令,即git cat-file -p <SHA1>打印内容。

于 2013-01-09T03:35:55.290 回答
8

看起来马克·阿德勒(Mark Adler)想到了我们,并写了一个关于如何做到这一点的示例:http ://www.zlib.net/zpipe.c

它只需要gcc -lz安装 zlib 头文件即可编译。我/usr/local/bin/zpipe在使用 git 东西时将生成的二进制文件复制到我的文件中。

于 2013-06-04T14:26:45.730 回答
6
// save this as deflate.go

package main

import (
    "compress/zlib"
    "io"
    "os"
    "flag"
)

var infile = flag.String("f", "", "infile")

func main() {
    flag.Parse()
    file, _ := os.Open(*infile)

    r, err := zlib.NewReader(file)
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, r)

    r.Close()
}

$ go build deflate.go
$ ./deflate -f .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7
于 2016-02-01T09:54:56.163 回答
2

git 对象是 zlib 流(不是原始放气)。pigz-dz将使用该选项解压缩那些。

于 2017-11-05T15:37:58.503 回答
2

pigz可以做到:

apt-get install pigz
unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7
于 2017-05-15T20:35:01.517 回答
1

请参阅http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations

它列出了许多软件实现,包括 gzip,因此应该可以工作。您是否尝试在文件上运行 gzip?它不会自动识别格式吗?

你怎么知道它是用 DEFLATE 压缩的?使用什么工具压缩文件?

于 2010-07-05T10:01:22.747 回答
1

我发现这个问题正在寻找解决我刚刚安装-text的新版本客户端中的实用程序错误的方法。hadoop dfs-text实用程序的工作方式类似于cat,除非正在读取的文件被压缩,它会透明地解压缩并输出纯文本(因此得名)。

已经发布的答案肯定很有帮助,但其中一些在处理 Hadoop 大小的数据量时存在一个问题 - 他们在解压缩之前将所有内容读入内存。

所以,这里是我对上面没有那个限制的答案Perl和答案的变体:Python

Python:

hadoop fs -cat /path/to/example.deflate |
  python -c 'import zlib,sys;map(lambda b:sys.stdout.write(zlib.decompress(b)),iter(lambda:sys.stdin.read(4096),""))'

珀尔:

hadoop fs -cat /path/to/example.deflate |
  perl -MCompress::Zlib -e 'print uncompress($buf) while sysread(STDIN,$buf,4096)'

注意-cat子命令的使用,而不是-text. 这是为了在他们修复错误后我的解决方法不会中断。为 python 版本的可读性道歉。

于 2014-05-13T16:22:43.877 回答
1

为什么不直接使用 git 的工具来访问数据呢?这应该能够读取任何 git 对象:

git show --pretty=raw <object SHA-1>
于 2010-07-05T10:22:47.213 回答
1

我反复遇到这个问题,似乎互联网上几乎所有的答案都是错误的,需要编译一些不太理想的代码,或者下载系统未跟踪的大量依赖项!但我找到了一个真正的解决方案。它使用 PERL,因为 PERL 在大多数系统上都很容易使用。

从类似 Bash 的外壳:

perl -mIO::Uncompress::RawInflate=rawinflate -erawinflate'"-","-"'

或者,如果您手动执行/分叉(没有外壳引号,但行分隔):

  • perl
  • -mIO::Uncompress::RawInflate=rawinflate
  • -erawinflate"-","-"

大警告:如果流不是作为有效的 DEFLATE 流开始的(例如,未压缩的数据),那么此命令将愉快地通过 untouched 管道传输所有数据。仅当流以有效的 DEFLATE 流开始时(我想使用有效的字典?我不太确定...),命令才会以某种方式出错。然而,在某些情况下,这可能是可取的。

希望这对任何时间旅行者都有帮助。

参考:

PERL IO::Uncompress::RawInflate::rawinflate

于 2021-11-03T19:00:57.310 回答
1

要添加到集合中,这里是用于 deflate/inflate/raw deflate/raw inflate 的 perl 单行代码。

放气

perl -MIO::Compress::Deflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Compress::Deflate::deflate(\$in, \$out); print $out;'

膨胀

perl -MIO::Uncompress::Inflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Uncompress::Inflate::inflate(\$in, \$out); print $out;'

原始放气

perl -MIO::Compress::RawDeflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Compress::RawDeflate::rawdeflate(\$in, \$out); print $out;'

原始膨胀

perl -MIO::Uncompress::RawInflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Uncompress::RawInflate::rawinflate(\$in, \$out); print $out;'
于 2019-05-29T08:59:27.347 回答
0
const zlib = require("zlib");
const adler32 = require("adler32");
const data = "hello world~!";
const chksum = adler32.sum(new Buffer(data)).toString(16);
console.log("789c",zlib.deflateRawSync(data).toString("hex"),chksum);
// or
console.log(zlib.deflateSync(data).toString("hex"));
于 2017-11-04T18:54:14.277 回答
0

这就是我使用 Powershell 的方式。

$fs = New-Object IO.FileStream((Resolve-Path $Path), [IO.FileMode]::Open, [IO.FileAccess]::Read)
$fs.Position = 2
$cs = New-Object IO.Compression.DeflateStream($fs, [IO.Compression.CompressionMode]::Decompress)
$sr = New-Object IO.StreamReader($cs)
$sr.ReadToEnd()

然后,您可以创建一个别名,例如:

function func_deflate{
    param(
        [Parameter(Mandatory=$true, ValueFromPipeline = $true)]
        [ValidateScript({Test-Path $_ -PathType leaf})]
        [string]$Path
    )
    $ErrorActionPreference = 'Stop'    
    $fs = New-Object IO.FileStream((Resolve-Path $Path), [IO.FileMode]::Open, [IO.FileAccess]::Read)
    $fs.Position = 2
    $cs = New-Object IO.Compression.DeflateStream($fs, [IO.Compression.CompressionMode]::Decompress)
    $sr = New-Object IO.StreamReader($cs)
    return $sr.ReadToEnd()
}

Set-Alias -Name deflate -Value func_deflate

在此处输入图像描述

于 2021-11-14T04:48:19.047 回答