1

这是我正在尝试的代码。

require 'zlib'
Dir.glob('*.*').each do |file|
  Zlib::GzipWriter.open('output.gz') do |gz|
    gz.mtime = File.mtime(file)
    gz.orig_name = File.basename(file)
    gz.write IO.binread(file)
  end
end

我已经尝试过不同的变体。似乎没有在线“多个文件”的操作指南。我一直以 ouput.gz 中的第一个文件名结尾,我认为它可能包含目录中最后一个文件的内容(不确定)。但这不是重点。我只想将每个文件作为单独的实体放在压缩文件中。越跨平台兼容越好。

4

2 回答 2

3

这个答案取自http://old.thoughtsincomputation.com/posts/tar-and-a-few-feathers-in-ruby,它是从RubyGems库中获取的。

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

module Util
  module Tar
    # Creates a tar file in memory recursively
    # from the given path.
    #
    # Returns a StringIO whose underlying String
    # is the contents of the tar file.
    def tar(path)
      tarfile = StringIO.new("")
      Gem::Package::TarWriter.new(tarfile) do |tar|
        Dir[File.join(path, "**/*")].each do |file|
          mode = File.stat(file).mode
          relative_file = file.sub /^#{Regexp::escape path}\/?/, ''

          if File.directory?(file)
            tar.mkdir relative_file, mode
          else
            tar.add_file relative_file, mode do |tf|
              File.open(file, "rb") { |f| tf.write f.read }
            end
          end
        end
      end

      tarfile.rewind
      tarfile
    end

    # gzips the underlying string in the given StringIO,
    # returning a new StringIO representing the 
    # compressed file.
    def gzip(tarfile)
      gz = StringIO.new("")
      z = Zlib::GzipWriter.new(gz)
      z.write tarfile.string
      z.close # this is necessary!

      # z was closed to write the gzip footer, so
      # now we need a new StringIO
      StringIO.new gz.string
    end

    # un-gzips the given IO, returning the
    # decompressed version as a StringIO
    def ungzip(tarfile)
      z = Zlib::GzipReader.new(tarfile)
      unzipped = StringIO.new(z.read)
      z.close
      unzipped
    end

    # untars the given IO into the specified
    # directory
    def untar(io, destination)
      Gem::Package::TarReader.new io do |tar|
        tar.each do |tarfile|
          destination_file = File.join destination, tarfile.full_name

          if tarfile.directory?
            FileUtils.mkdir_p destination_file
          else
            destination_directory = File.dirname(destination_file)
            FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
            File.open destination_file, "wb" do |f|
              f.print tarfile.read
            end
          end
        end
      end
    end
  end
end


### Usage Example: ###
#
# include Util::Tar
# 
# io = tar("./Desktop")   # io is a TAR of files
# gz = gzip(io)           # gz is a TGZ
# 
# io = ungzip(gz)         # io is a TAR
# untar(io, "./untarred") # files are untarred
#
于 2014-10-23T20:57:21.660 回答
2

首先,这将继续覆盖output.gz,使其仅包含最后一个压缩文件。

其次,gzip 格式不包含多个文件。它只有一个。您需要使用.tar.gzor.zip格式。 .zip更“跨平台兼容”。看看ruby​​zip

于 2012-12-19T04:14:29.123 回答