如何使用 Rubyzip lib 覆盖现有文件

发布于 2024-07-23 18:33:53 字数 410 浏览 8 评论 0原文

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

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

这是我的代码:

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

I'm attempting to unzip a file with several files that may or may not already exist in the target directory. It seems the default behavior is to throw an exception if the file already exists.

How do I unzip to a directory and simply overwrite existing files?

Here's my code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

手长情犹 2024-07-30 18:33:53

只是为了省去其他人的麻烦:

答案 2 中的 extract 命令不正确:

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

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

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

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

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

Just to save others the trouble:

The extract command in answer 2 is incorrect:

The third (proc) parameter is specified wtih an ampersand, meaning ruby expects it to be in {}-Brackets after the method call like this:

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

or (if you need more complex logic)

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

If you use the example given in Post #2 you'll get a "invalid arguments (3 for 2)" error...

简美 2024-07-30 18:33:53

看来 extract() 采用一个可选块 (onExistsProc),允许您确定如何处理文件(如果文件已存在) - 返回 true 进行覆盖,返回 false 引发异常。

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

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

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

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

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

It appears that extract() takes an optional block (onExistsProc) that allows you to determine what to do with the file if it already exists - return true to overwrite, false to raise an exception.

If you wanted to simply overwrite all existing files, you could do:

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

If you want to do some more complex logic to handle specific entries differently, you can do:

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

EDIT: fixed answer - as pointed out by Ingmar Hamer, my original answer passed the block as a parameter when it's expected using the above syntax.

左秋 2024-07-30 18:33:53

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

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

Edit: Modified code to remove target file if it exists beforehand.

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

Edit: Modified code to remove target directory if it exists beforehand.

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

Here's 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')
毅然前行 2024-07-30 18:33:53

链接提供了一个很好的例子,我已经验证了它的工作原理。 只需要添加一个 require 'fileutils' 即可。

This link here provides a good example which I have verified works. Just needs to have a require 'fileutils' added to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文