2009-05-13 35 views

Respuesta

27

para extraer archivos de un archivo .tar.gz se pueden utilizar los siguientes métodos de paquetes distribuidos con 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 del tipo Gem::Package::TarReader::Entry puntos a un archivo o directorio dentro del .tar.gz archivo.

Se puede usar un código similar (reemplace Reader with Writer) para escribir archivos en un archivo .tar.gz.

27

La forma más sencilla es utilizar probablemente Zlib

Zlib es una biblioteca de Ruby. Lo que sigue es un programa simple para tomar un archivo comprimido de una URL en particular, descomprimirlo y pegar sus contenidos en la pantalla.

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 esto ayude.

+0

Mavryx: Cuando estoy tratando el fragmento que estoy recibiendo el siguiente error: unzip.rb: 5: variable local no está definido o método 'uri' para # (NameError) – maetthew

+0

@maetthew marque la línea 4 y asegúrese de usar la misma variable (uri aquí) en ambas líneas – BurmajaM

10

Aunque Florian's answer es correcto, no tiene en cuenta tar LongLinks (Intente extraer jdk-7u40-linux-i586.tar.gz de oráculo: P). El siguiente código debe ser capaz de hacer esto:

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 
+0

es ': verbose = > falso' necesario? –

+0

No, simplemente no quería que se imprimiera nada en mi caso de uso. –

1

Draco, THX para usted snippet. Algunos TAR codifican directorios como rutas que terminan con '/' - vea this Wiki. Examlple tar es Oracle Server JRE 7u80 for Windows. Esto funcionará para ellos:

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 
Cuestiones relacionadas