2009-06-08 22 views
7

対象のディレクトリに存在していてもいなくてもよい複数のファイルを解凍しようとしています。既定の動作は、ファイルが既に存在する場合に例外をスローすることです。Rubyzip libを使用して既存のファイルを上書きする方法

ディレクトリに解凍して既存のファイルを上書きするにはどうすればよいですか?

ここに私のコードは次のとおりです。

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を返します例外を発生させるにはfalseを返します。

あなたは、単にすべての既存のファイルを上書きしたい場合は、あなたができる:

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

あなたは違った特定のエントリを処理するためにいくつかのより複雑なロジックをしたい場合は、あなたが行うことができます:

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

EDIT:固定答え - Ingmar Hamerによって指摘されているように、私の元の答えは、上記の構文を使用すると予想されるときにパラメータとしてブロックを渡しました。

+0

この回答は実際には掲載されていません。 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

+0

...確かに存在するファイルをスキップします。投稿する前に特定のユースケースをテストしないでください。謝罪いたします。私の編集されたバージョンを参照してください。それはあらかじめ存在する場合、コピー先ディレクトリを削除します。 – bernie

+0

私の2番目の解決策も最適ではありませんでした。おそらく、ディレクトリ全体を削除することはお勧めできません。 3回目は魅力的だと思います。新しいファイルを書き込む前にファイルを削除するコードを少し追加しました。 – bernie

14

ただ、他の人に迷惑保存するには:

答え2で抽出コマンドを正しくありません。第三(PROC)パラメータはアンパサンドwtih指定されている

、ルビーを意味することは、{}であることを期待 - このようなメソッド呼び出しの後の括弧:

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

または(あなたがより複雑なロジックを必要とする場合)

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

Post#2で指定された例を使用すると、「無効な引数(3の2)」というエラーが発生します...

+0

ありがとうございます。私はRubyを初めて使い、この特定の壁に対して1時間頭を打つ。 –

0

このlink hereは、私が検証した良い例です。ちょうど必要な 'fileutils'が追加されている必要があります。

関連する問題