2009-06-08 42 views
7

我试图解压缩一个文件,其中可能包含或可能不存在于目标目录中的多个文件。看起来默认行为是在文件已经存在的情况下抛出异常。如何使用Rubyzip库覆盖现有文件

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

这里是我的代码:

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 

回答

12

看来,提取物()接受一个可选的块(onExistsProc),它允许你以确定哪些对文件进行操作,如果它已经存在 - 返回true以覆盖,假提出异常。

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

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

如果你想要做一些更复杂的逻辑,以不同的方式处理特定条目,你可以这样做:

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

编辑:修正答案 - 正如Ingmar Hamer所指出的那样,当我的原始答案使用上面的语法时,我的原始答案通过块作为参数。

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') 

这里的the original code from 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') 
+0

感谢您的答案,但它看起来像不会覆盖现有的文件。如果它存在,它会跳过它。 – digitalsanctum 2009-06-08 19:37:17

+0

...确实它跳过存在的文件。在发布之前,我多么愚蠢地没有测试该特定用例。我很抱歉。请参阅我的编辑版本,如果它预先存在,将删除目标目录。 – bernie 2009-06-08 19:56:16

+0

而我的第二个解决方案也不理想。因为删除整个目录可能不太可取;但我相信第三次是一种魅力:我添加了一些代码来删除文件,如果它在写入新文件之前存在。 – bernie 2009-06-08 20:03:41

14

只是为了保存他人的麻烦:

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

第三(PROC)参数wtih一个符号指定,这意味着红宝石希望它是在{} - 这样的方法调用后的括号:

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

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

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

如果您使用Post#2中给出的示例,您将得到一个“无效参数(3 for 2)”错误...

0

这个link here提供了一个很好的例子,我已经验证了作品。只需要添加一个require'fileutils'即可。