Desinflar herramienta de command-line

Estoy buscando un contenedor de línea de command para el algorithm DEFLATE.

Tengo un file (git blob) que está comprimido usando DEFLATE, y quiero descomprimirlo. El command gzip no parece tener una opción para usar directamente el algorithm DEFLATE, en lugar del formatting gzip.

Idealmente, estoy buscando una herramienta estándar de Unix / Linux que pueda hacer esto.

editar: este es el resultado que obtengo cuando trato de usar gzip para mi problema:

$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip gzip: stdin: not in gzip format 

ACTUALIZACIÓN: Mark Adler notó que los blobs git no son flujos DEFLATE sin procesar, sino zlib. Estos pueden ser desempaquetados por la herramienta pigz , que viene preempaquetada en varias distribuciones de 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! 

Mi respuesta original, guardada por razones históricas:

Si entiendo la sugerencia en el artículo de Wikipedia mencionado por Marc van Kempen, puedes usar puff.c desde zlib directamente.

Este es un pequeño ejemplo:

 #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 ); } 

Algo como lo siguiente imprimirá el contenido sin formatting, incluido el encabezado "$ type $ length \ 0":

 perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' \ < .git/objects/27/de0a1dd5a89a94990618632967a1c86a82d577 

Puede hacer esto con la herramienta de command-line de OpenSSL:

 openssl zlib -d < $IN > $OUT 

Desafortunadamente, al less en Ubuntu, el subcommand zlib está deshabilitado en la configuration de compilation pnetworkingeterminada ( --no-zlib --no-zlib-dynamic ), por lo que necesitaría comstackr openssl desde el origen para usarlo. Pero está habilitado por defecto en Arch, por ejemplo.

Editar: parece que el command zlib ya no es compatible con Arch. Esta respuesta puede que ya no sea útil 🙁

pythonic one-liner:

 $> python -c "import zlib,sys;print \ repr(zlib.decompress(sys.stdin.read()))" < $IN 

Puedes usar zlib-flate, así:

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

Está allí por defecto en mi máquina, pero es parte de qpdf - tools for and transforming and inspecting PDF files si necesita instalarlo.

He echo un echo al final del command, ya que es más fácil leer la salida de esa manera.

Pruebe el siguiente command:

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

No se necesitan herramientas externas.

Fuente: ¿Cómo descomprimir datos zlib en UNIX? en Unix SE

Aquí hay un Ruby one-liner (cd .git / first e identifica la ruta a cualquier object):

 ruby -rzlib -e 'print Zlib::Inflate.new.inflate(STDIN.read)' < ./74/c757240ec596063af8cd273ebd9f67073e1208 

Aquí hay un ejemplo de cómo abrir un object de commit en 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! 

Lo que verá allí es casi idéntico al resultado de 'git cat-file -p [hash]', excepto que el command no imprime el encabezado ('commit' seguido del tamaño del contenido y un byte nulo).

Me cansé de no tener una buena solución para esto, así que puse algo en NPM:

https://github.com/jezell/zlibber

Ahora puede simplemente canalizar para inflar / desinflar el command.

Parece que Mark Adler nos tiene en count y escribió un ejemplo de cómo hacer esto con: http://www.zlib.net/zpipe.c

Comstack con nada más que gcc -lz y los encabezados zlib instalados. Copié el binary resultante en mi /usr/local/bin/zpipe mientras trabajaba con git stuff.

Los objects git son comprimidos por zlib lugar de por gzip , por lo que se usa zlib para descomprimirlo o command git, es decir, git cat-file -p <SHA1> , para imprimir contenido.

 // 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 

Ver http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations

Enumera una serie de implementaciones de software, incluido gzip, por lo que debería funcionar. ¿Intentó simplemente ejecutar gzip en el file? ¿No reconoce el formatting automáticamente?

¿Cómo sabes que está comprimido usando DEFLATE? ¿Qué herramienta se utilizó para comprimir el file?

Encontré esta pregunta buscando una solución -text con un error con la utilidad -text en la nueva versión del cliente de hadoop dfs que acabo de instalar. La utilidad -text funciona como cat , excepto si el file que se está leyendo está comprimido, descomprime y saca el text sin formatting (de ahí el nombre).

Las respuestas ya publicadas fueron definitivamente útiles, pero algunas tienen un problema cuando se trata de cantidades de datos del tamaño de Hadoop: leen todo en la memory antes de descomprimir.

Entonces, aquí están mis variaciones sobre las respuestas de Perl y Python anteriores que no tienen esa limitación:

Pitón:

 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),""))' 

Perl:

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

Tenga en count el uso del -cat , en lugar de -text . Esto es para que mi trabajo no se rompa después de haber solucionado el error. Disculpas por la legibilidad de la versión de Python.

Los objects git son flujos zlib (no desinflados en bruto). pigz descomprimirá aquellos con la opción -dz .

¿Por qué no utilizas las herramientas de git para acceder a los datos? Esto debería poder leer cualquier object git:

 git show --pretty=raw <object SHA-1> 

Pigz puede hacerlo:

 apt-get install pigz unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 
 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"));