распаковать (zip, tar, tag.gz) файлы с помощью ruby - PullRequest
29 голосов
/ 13 мая 2009

Я хочу распаковать много zip-файлов. Есть ли модуль или скрипт, который проверяет, в каком формате находится файл zip, и распаковывает его? Это должно работать в Linux, мне нет дела до других ОС.

Ответы [ 4 ]

28 голосов
/ 16 июля 2012

Для извлечения файлов из файла .tar.gz вы можете использовать следующие методы из пакетов, распространяемых с 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

Каждая запись типа Gem :: Package :: TarReader :: Entry указывает на файл или каталог в файле .tar.gz.

Аналогичный код можно использовать (замените Reader на Writer) для записи файлов в файл .tar.gz.

28 голосов
/ 06 января 2010

Самый простой способ - использовать Zlib

.

Zlib - это библиотека Ruby. Ниже приведена простая программа, позволяющая получить файл Zip с определенного URL-адреса, распаковать его и вставить его содержимое на экран.

require 'zlib' 
require 'open-uri'

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

Надеюсь, это поможет.

12 голосов
/ 02 октября 2013

Хотя ответ Флориана прав, он не учитывает tar LongLinks (Попробуйте извлечь jdk-7u40-linux-i586.tar.gz из оракул: P). Следующий код должен быть в состоянии сделать это:

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
2 голосов
/ 09 июля 2015

Драко, спасибо тебе фрагмент . Некоторые TAR кодируют каталоги как пути, заканчивающиеся на '/' - см. this Wiki. Примером tar является Oracle Server JRE 7u80 для Windows . Это будет работать для них:

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