lib/archive/zip.rb
def extract(destination, options = {})
      raise IOError, 'non-readable archive' unless readable?
      raise IOError, 'closed archive' if closed?

      # Ensure that unspecified options have default values.
      options[:directories] = true  unless options.has_key?(:directories)
      options[:symlinks]    = false unless options.has_key?(:symlinks)
      options[:overwrite]   = :all  unless options[:overwrite] == :older ||
                                           options[:overwrite] == :never
      options[:create]      = true  unless options.has_key?(:create)
      options[:flatten]     = false unless options.has_key?(:flatten)

      # Flattening the archive structure implies that directory entries are
      # skipped.
      options[:directories] = false if options[:flatten]

      # First extract all non-directory entries.
      directories = []
      each do |entry|
        # Compute the target file path.
        file_path = entry.zip_path
        file_path = File.basename(file_path) if options[:flatten]
        file_path = File.join(destination, file_path)

        # Cache some information about the file path.
        file_exists = File.exist?(file_path)
        file_mtime = File.mtime(file_path) if file_exists

        begin
          # Skip this entry if so directed.
          if (! file_exists && ! options[:create]) ||
             (file_exists &&
              (options[:overwrite] == :never ||
               options[:overwrite] == :older && entry.mtime <= file_mtime)) ||
             (! options[:exclude].nil? && options[:exclude][entry]) then
            next
          end

          # Set the decryption key for the entry.
          if options[:password].kind_of?(String) then
            entry.password = options[:password]
          elsif ! options[:password].nil? then
            entry.password = options[:password][entry]
          end

          if entry.directory? then
            # Record the directories as they are encountered.
            directories << entry
          elsif entry.file? || (entry.symlink? && options[:symlinks]) then
            # Extract files and symlinks.
            entry.extract(
              options.merge(:file_path => file_path)
            )
          end
        rescue StandardError => error
          unless options[:on_error].nil? then
            case options[:on_error][entry, error]
            when :retry
              retry
            when :skip
            else
              raise
            end
          else
            raise
          end
        end
      end

      if options[:directories] then
        # Then extract the directory entries in depth first order so that time
        # stamps, ownerships, and permissions can be properly restored.
        directories.sort { |a, b| b.zip_path <=> a.zip_path }.each do |entry|
          begin
            entry.extract(
              options.merge(
                :file_path => File.join(destination, entry.zip_path)
              )
            )
          rescue StandardError => error
            unless options[:on_error].nil? then
              case options[:on_error][entry, error]
              when :retry
                retry
              when :skip
              else
                raise
              end
            else
              raise
            end
          end
        end
      end

      nil
    end
def extract(destination, options = {})
      raise IOError, 'non-readable archive' unless readable?
      raise IOError, 'closed archive' if closed?

      # Ensure that unspecified options have default values.
      options[:directories] = true  unless options.has_key?(:directories)
      options[:symlinks]    = false unless options.has_key?(:symlinks)
      options[:overwrite]   = :all  unless options[:overwrite] == :older ||
                                           options[:overwrite] == :never
      options[:create]      = true  unless options.has_key?(:create)
      options[:flatten]     = false unless options.has_key?(:flatten)

      # Flattening the archive structure implies that directory entries are
      # skipped.
      options[:directories] = false if options[:flatten]

      # First extract all non-directory entries.
      directories = []
      each do |entry|
        # Compute the target file path.
        file_path = entry.zip_path
        file_path = File.basename(file_path) if options[:flatten]
        file_path = File.join(destination, file_path)

        # Cache some information about the file path.
        file_exists = File.exist?(file_path)
        file_mtime = File.mtime(file_path) if file_exists

        begin
          # Skip this entry if so directed.
          if (! file_exists && ! options[:create]) ||
             (file_exists &&
              (options[:overwrite] == :never ||
               options[:overwrite] == :older && entry.mtime <= file_mtime)) ||
             (! options[:exclude].nil? && options[:exclude][entry]) then
            next
          end

          # Set the decryption key for the entry.
          if options[:password].kind_of?(String) then
            entry.password = options[:password]
          elsif ! options[:password].nil? then
            entry.password = options[:password][entry]
          end

          if entry.directory? then
            # Record the directories as they are encountered.
            directories << entry
          elsif entry.file? || (entry.symlink? && options[:symlinks]) then
            # Extract files and symlinks.
            entry.extract(
              options.merge(:file_path => file_path)
            )
          end
        rescue StandardError => error
          unless options[:on_error].nil? then
            case options[:on_error][entry, error]
            when :retry
              retry
            when :skip
            else
              raise
            end
          else
            raise
          end
        end
      end

      if options[:directories] then
        # Then extract the directory entries in depth first order so that time
        # stamps, ownerships, and permissions can be properly restored.
        directories.sort { |a, b| b.zip_path <=> a.zip_path }.each do |entry|
          begin
            entry.extract(
              options.merge(
                :file_path => File.join(destination, entry.zip_path)
              )
            )
          rescue StandardError => error
            unless options[:on_error].nil? then
              case options[:on_error][entry, error]
              when :retry
                retry
              when :skip
              else
                raise
              end
            else
              raise
            end
          end
        end
      end

      nil
    end
def extract ( destination , options = { } ) raise IOError , 'non-readable archive' unless readable? raise IOError , 'closed archive' if closed? # Ensure that unspecified options have default values. options [ :directories ] = true unless options . has_key? ( :directories ) options [ :symlinks ] = false unless options . has_key? ( :symlinks ) options [ :overwrite ] = :all unless options [ :overwrite ] == :older || options [ :overwrite ] == :never options [ :create ] = true unless options . has_key? ( :create ) options [ :flatten ] = false unless options . has_key? ( :flatten ) # Flattening the archive structure implies that directory entries are # skipped. options [ :directories ] = false if options [ :flatten ] # First extract all non-directory entries. directories = [ ] each do | entry | # Compute the target file path. file_path = entry . zip_path file_path = File . basename ( file_path ) if options [ :flatten ] file_path = File . join ( destination , file_path ) # Cache some information about the file path. file_exists = File . exist? ( file_path ) file_mtime = File . mtime ( file_path ) if file_exists begin # Skip this entry if so directed. if ( ! file_exists && ! options [ :create ] ) || ( file_exists && ( options [ :overwrite ] == :never || options [ :overwrite ] == :older && entry . mtime <= file_mtime ) ) || ( ! options [ :exclude ] . nil? && options [ :exclude ] [ entry ] ) then next end # Set the decryption key for the entry. if options [ :password ] . kind_of? ( String ) then entry . password = options [ :password ] elsif ! options [ :password ] . nil? then entry . password = options [ :password ] [ entry ] end if entry . directory? then # Record the directories as they are encountered. directories << entry elsif entry . file? || ( entry . symlink? && options [ :symlinks ] ) then # Extract files and symlinks. entry . extract ( options . merge ( :file_path => file_path ) ) end rescue StandardError => error unless options [ :on_error ] . nil? then case options [ :on_error ] [ entry , error ] when :retry retry when :skip else raise end else raise end end end if options [ :directories ] then # Then extract the directory entries in depth first order so that time # stamps, ownerships, and permissions can be properly restored. directories . sort { | a , b | b . zip_path <=> a . zip_path } . each do | entry | begin entry . extract ( options . merge ( :file_path => File . join ( destination , entry . zip_path ) ) ) rescue StandardError => error unless options [ :on_error ] . nil? then case options [ :on_error ] [ entry , error ] when :retry retry when :skip else raise end else raise end end end end nil end
Extracts the contents of the archive to _destination_, where _destination_
 is a path to a directory which will contain the contents of the archive.
 The destination path will be created if it does not already exist.

 _options_ is a Hash optionally containing the following:
 <b>:directories</b>::
   When set to +true+ (the default), entries representing directories in
   the archive are extracted.  This happens after all non-directory entries
   are extracted so that directory metadata can be properly updated.
 <b>:symlinks</b>::
   When set to +false+ (the default), entries representing symlinks in the
   archive are skipped.  When set to +true+, such entries are extracted.
   Exceptions may be raised on plaforms/file systems which do not support
   symlinks.
 <b>:overwrite</b>::
   When set to <tt>:all</tt> (the default), files which already exist will
   be replaced.  When set to <tt>:older</tt>, such files will only be
   replaced if they are older according to their last modified times than
   the zip entry which would replace them.  When set to <tt>:none</tt>,
   such files will never be replaced.  Any other value is the same as
   <tt>:all</tt>.
 <b>:create</b>::
   When set to +true+ (the default), files and directories which do not
   already exist will be extracted.  When set to +false+, only files and
   directories which already exist will be extracted (depending on the
   setting of <b>:overwrite</b>).
 <b>:flatten</b>::
   When set to +false+ (the default), the directory paths containing
   extracted files will be created within +destination+ in order to contain
   the files.  When set to +true+, files are extracted directly to
   +destination+ and directory entries are skipped.
 <b>:exclude</b>::
   Specifies a proc or lambda which takes a single argument containing a
   zip entry and returns +true+ if the entry should be skipped during
   extraction and +false+ if it should be extracted.
 <b>:password</b>::
   Specifies a proc, lambda, or a String.  If a proc or lambda is used, it
   must take a single argument containing a zip entry and return a String
   to be used as a decryption key for the entry.  If a String is used, it
   will be used as a decryption key for all encrypted entries.
 <b>:on_error</b>::
   Specifies a proc or lambda which is called when an exception is raised
   during the extraction of an entry.  It takes two arguments, a zip entry
   and an exception object generated while attempting to extract the entry.
   If <tt>:retry</tt> is returned, extraction of the entry is attempted
   again.  If <tt>:skip</tt> is returned, the entry is skipped.  Otherwise,
   the exception is raised.
 Any other options which are supported by Archive::Zip::Entry#extract are
 also supported.

 Raises Archive::Zip::IOError if called on a non-readable archive or after
 the archive is closed.

 == Example

 An archive, <tt>archive.zip</tt>, contains:
   zip-test/
   zip-test/dir1/
   zip-test/dir1/file2.txt
   zip-test/dir2/
   zip-test/file1.txt

 A directory, <tt>extract4</tt>, contains:
   zip-test
   +- dir1
   +- file1.txt

 Extract the archive:
   Archive::Zip.open('archive.zip') do |z|
     z.extract('extract1')
   end

   Archive::Zip.open('archive.zip') do |z|
     z.extract('extract2', :flatten => true)
   end

   Archive::Zip.open('archive.zip') do |z|
     z.extract('extract3', :create => false)
   end

   Archive::Zip.open('archive.zip') do |z|
     z.extract('extract3', :create => true)
   end

   Archive::Zip.open('archive.zip') do |z|
     z.extract( 'extract5', :exclude => lambda { |e| e.file? })
   end

 The directories contain:
   extract1 -> zip-test
               +- dir1
               |  +- file2.txt
               +- dir2
               +- file1.txt

   extract2 -> file2.txt
               file1.txt

   extract3 -> <empty>

   extract4 -> zip-test
               +- dir2
               +- file1.txt       <- from archive contents

   extract5 -> zip-test
               +- dir1
               +- dir2
Extracts the contents of the archive to _destination_ where _destination_ is a path to a directory which will contain the contents of the archive . The destination path will be created if it does not already exist .