Pergunta

Eu quero descompactar um monte de arquivos zip. Existe um módulo ou script que verifica qual o formato do arquivo zip é e descompacta-lo? Isso deve funcionar no Linux, eu não me importo com outros SOs.

Foi útil?

Solução

Para extrair arquivos de um arquivo .tar.gz você pode usar os seguintes métodos de pacotes distribuídos com Ruby:

require 'rubygems/package'
require 'zlib'
tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open('Path/To/myfile.tar.gz'))
tar_extract.rewind # The extract has to be rewinded after every iteration
tar_extract.each do |entry|
  puts entry.full_name
  puts entry.directory?
  puts entry.file?
  # puts entry.read
end
tar_extract.close

Cada entrada do tipo Gem :: pacote :: TarReader :: entrada aponta para um arquivo ou pasta dentro do arquivo .tar.gz.

código semelhante pode ser utilizado (substitua Reader com Writer) para gravar arquivos para um arquivo .tar.gz.

Outras dicas

A maneira mais fácil é provavelmente usar Zlib

Zlib é uma biblioteca Ruby. O que se segue é um programa simples para pegar um arquivo zipado de um URL particular, descompactá-lo e colar o seu conteúdo para a tela.

require 'zlib' 
require 'open-uri'

uri = "www.somedomain.com/filename.gz"
source = open(uri)
gz = Zlib::GzipReader.new(source) 
result = gz.read
puts result

Espero que isso ajude.

Apesar de resposta de Florian é certo, ele não leva em conta tar LongLinks (Tente extrair jdk-7u40-linux i586.tar.gz da oracle: P). O código a seguir deve ser capaz de fazer isso:

require 'rubygems/package'
require 'zlib'

TAR_LONGLINK = '././@LongLink'
tar_gz_archive = '/path/to/archive.tar.gz'
destination = '/where/extract/to'

Gem::Package::TarReader.new( Zlib::GzipReader.open tar_gz_archive ) do |tar|
  dest = nil
  tar.each do |entry|
    if entry.full_name == TAR_LONGLINK
      dest = File.join destination, entry.read.strip
      next
    end
    dest ||= File.join destination, entry.full_name
    if entry.directory?
      File.delete dest if File.file? dest
      FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
    elsif entry.file?
      FileUtils.rm_rf dest if File.directory? dest
      File.open dest, "wb" do |f|
        f.print entry.read
      end
      FileUtils.chmod entry.header.mode, dest, :verbose => false
    elsif entry.header.typeflag == '2' #Symlink!
      File.symlink entry.header.linkname, dest
    end
    dest = nil
  end
end

Draco, thx para você trecho . Alguns TARs codificar diretórios como caminhos terminando com '/' - veja este Wiki. Examlple alcatrão é servidor Oracle JRE 7u80 para Windows . Isto irá trabalhar para eles:

require 'fileutils'
require 'rubygems/package'
require 'zlib'

TAR_LONGLINK = '././@LongLink'

Gem::Package::TarReader.new( Zlib::GzipReader.open tar_gz_archive ) do |tar|
        dest = nil
        tar.each do |entry|
            if entry.full_name == TAR_LONGLINK
                dest = File.join destination, entry.read.strip
                next
            end
            dest ||= File.join destination, entry.full_name
            if entry.directory? || (entry.header.typeflag == '' && entry.full_name.end_with?('/'))
                File.delete dest if File.file? dest
                FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
            elsif entry.file? || (entry.header.typeflag == '' && !entry.full_name.end_with?('/'))
                FileUtils.rm_rf dest if File.directory? dest
                File.open dest, "wb" do |f|
                    f.print entry.read
                end
                FileUtils.chmod entry.header.mode, dest, :verbose => false
            elsif entry.header.typeflag == '2' #Symlink!
                File.symlink entry.header.linkname, dest
            else
                puts "Unkown tar entry: #{entry.full_name} type: #{entry.header.typeflag}."
            end
            dest = nil
        end
    end
end
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top