2009-06-08 43 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'即可。