rubyrubyzip

Rubyzip fail to add a file with a same name from another folder [Zip::EntryExistsError]


Using the following test tree folder for example:

- test1
- folder2
  - test1 # This is the file rubyzip will break on.
  - test2

And copied this code from here:

path = File.expand_path path
archive = File.join(__dir__, File.basename(path)) + '.zip'
FileUtils.rm archive, force: true

Zip::File.open(archive, Zip::File::CREATE) do | zipfile |
  Dir["#{path}/**/**"].reject{|f|f==archive}.each do | item |
    basename = File.basename(item)
    zipfile.add(basename, item)
  end
end

It fails because there is two files having the same name even if their are not in the same directory (test1 in my example).

Is there something I am missing ?


Solution

  • Thanks to @simonoff (here), I shouldn't use the basename but the full relative path so Rubyzip could make the difference between test1 and folder2/test1.

    Here is a code fixing it:

    basename = File.basename path
    dirname = File.dirname path
    internal_path = path.sub %r[^#{__dir__}/], ''
    
    archive = File.join(dirname, basename) + '.zip'
    FileUtils.rm archive, force: true
    
    Zip::File.open(archive, Zip::File::CREATE) do | zipfile |
      Dir["#{internal_path}/**/**"].map{|e|e.sub %r[^#{internal_path}/],''}.reject{|f|f==archive}.each do | item |
        zipfile.add(item, File.join(internal_path, item))
      end
    end
    

    There is certainly a much cleaner way to do it.