11

我正在尝试解压缩一个包含多个文件的文件,这些文件可能已经存在也可能不存在于目标目录中。如果文件已经存在,默认行为似乎是抛出异常。

如何解压缩到目录并简单地覆盖现有文件?

这是我的代码:

begin
  Zip::ZipFile.open(source) do |zipfile|
    dir = zipfile.dir
    dir.entries('.').each do |entry|
      zipfile.extract(entry, "#{target}/#{entry}")
    end
  end
rescue Exception => e
  log_error("Error unzipping file: #{local_zip}  #{e.to_s}")
end
4

4 回答 4

17

只是为了省去别人的麻烦:

答案 2 中的提取命令不正确:

第三个 (proc) 参数用 & 符号指定,这意味着 ruby​​ 期望它在方法调用之后的 {}-Brackets 中,如下所示:

zipfile.extract(entry, "#{target}/#{entry}"){ true }

或(如果您需要更复杂的逻辑)

zipfile.extract(entry, "#{target}/#{entry}") {|entry, path| some_logic(entry, path) }

如果您使用 Post #2 中给出的示例,您将收到“invalid arguments (3 for 2)”错误...

于 2009-10-09T10:29:50.047 回答
15

似乎 extract() 采用了一个可选块 (onExistsProc),它允许您确定如果文件已经存在如何处理它 - 返回 true 以覆盖,返回 false 以引发异常。

如果你想简单地覆盖所有现有文件,你可以这样做:

zipfile.extract(entry, "#{target}/#{entry}") { true }

如果您想执行一些更复杂的逻辑来以不同方式处理特定条目,您可以执行以下操作:

zipfile.extract(entry, "#{target}/#{entry}") {|entry, path| some_logic(entry, path) }

编辑:固定答案 - 正如 Ingmar Hamer 所指出的,我的原始答案在预期使用上述语法时将块作为参数传递。

于 2009-06-08T20:26:23.373 回答
1

编辑:修改代码以删除目标文件(如果它事先存在)。

require 'rubygems'
require 'fileutils'
require 'zip/zip'

def unzip_file(file, destination)
  Zip::ZipFile.open(file) { |zip_file|
   zip_file.each { |f|
     f_path=File.join(destination, f.name)
     if File.exist?(f_path) then
       FileUtils.rm_rf f_path
     end
     FileUtils.mkdir_p(File.dirname(f_path))
     zip_file.extract(f, f_path)
   }
  }
end

unzip_file('/path/to/file.zip', '/unzip/target/dir')

编辑:修改代码以删除目标目录(如果它事先存在)。

require 'rubygems'
require 'fileutils'
require 'zip/zip'

def unzip_file(file, destination)
  if File.exist?(destination) then
    FileUtils.rm_rf destination
  end
  Zip::ZipFile.open(file) { |zip_file|
   zip_file.each { |f|
     f_path=File.join(destination, f.name)
     FileUtils.mkdir_p(File.dirname(f_path))
     zip_file.extract(f, f_path)
   }
  }
end

unzip_file('/path/to/file.zip', '/unzip/target/dir')

这是来自 Mark Needham 的原始代码

require 'rubygems'
require 'fileutils'
require 'zip/zip'

def unzip_file(file, destination)
  Zip::ZipFile.open(file) { |zip_file|
   zip_file.each { |f|
     f_path=File.join(destination, f.name)
     FileUtils.mkdir_p(File.dirname(f_path))
     zip_file.extract(f, f_path) unless File.exist?(f_path)
   }
  }
end

unzip_file('/path/to/file.zip', '/unzip/target/dir')
于 2009-06-08T19:17:54.977 回答
0

这里的这个链接提供了一个很好的例子,我已经验证了它的作品。只需要添加一个 require 'fileutils' 。

于 2010-04-12T15:14:36.430 回答