#!/usr/bin/env ruby # Note this doesn't deal with directories in zip files. # That's documented elsewhere. The recursive processing of # zip files in zip files was the tricky bit. require 'zip' def recursive_zip_reader(input) if input.is_a? String zip_file = Zip::File.open(input) recursive_zip_file_reader(zip_file) elsif input.is_a? Zip::File recursive_zip_file_reader(input) elsif input.is_a? Zip::Entry recursive_zip_entry_reader(input) elsif input.is_a? File recursive_zip_file_reader(Zip::File.open(input.path)) else "unknown input type (#{input.class}): #{input}" end end def recursive_zip_file_reader(zip_file) file_names = [] zip_file.entries.each do | zip_entry | # nobody wants macOS's bs finder metadata files next if zip_entry.name.start_with?("__MACOSX") file_names << recursive_zip_entry_reader(zip_entry) end file_names end def recursive_zip_entry_reader(zip_entry) name = zip_entry.name return name unless name.end_with?(".zip") entry_contents = zip_entry.get_input_stream.read nested_entry = Zip::File.open_buffer(entry_contents) {name => recursive_zip_reader(nested_entry)} end puts recursive_zip_reader("multizip.zip").inspect # output should look like this # [ # { # "subzip.zip": [ # "pass.json", # "manifest.json", # "signature" # ] # } # ]