RubyGems Version License Build Status

Excavate

Recursive Archive Extraction

Excavate provides a unified interface for extracting nested archives across multiple compression and archive formats.

It allows for the extraction of a particular file from a deeply nested archives potentially spanning multiple formats (e.g., extracting a file from a CAB inside an MSI installer) with a single command, handling all the complexities of different formats and platform-specific issues under the hood.

Excavate is a pure Ruby gem with no native dependencies:

  • No compilation required

  • Works on MRI, JRuby, and TruffleRuby

  • Cross-platform: Linux, macOS, Windows, BSD

  • Easy deployment with no system dependencies

Part of the Omnizip Suite — Pure Ruby compression libraries

Built on Omnizip and Cabriolet, it enables recursive extraction of archives within archives with a single command.

Omnizip and Cabriolet are libraries that handle the core extraction logic and are used for extracting single layers of archives. Excavate provides the high-level interface that orchestrates recursive extraction across multiple formats, leveraging Omnizip and Cabriolet under the hood.

Why Excavate?

  • Recursive Extraction: Extract archives within archives automatically (e.g., MSI → CAB → files)

  • Unified API: One consistent interface for 10+ archive formats

  • Pure Ruby: No native dependencies, works everywhere Ruby runs

  • Selective Extraction: Extract specific files or filter by pattern

  • CLI Included: Command-line tool for quick extraction tasks

  • Cross-Platform: Handles Windows file locking, works on all platforms

Quick Start

Installation

gem install excavate

Or add to your Gemfile:

gem "excavate"

Basic Usage

require "excavate"

# Extract an archive
Excavate::Archive.new("package.zip").extract

# Extract recursively (nested archives)
Excavate::Archive.new("installer.msi").extract(recursive_packages: true)

# Extract specific files
Excavate::Archive.new("data.tar.gz").extract(files: ["config/settings.json"])

# Filter by pattern
Excavate::Archive.new("fonts.zip").extract(filter: "**/*.ttf")

Supported Formats

Excavate supports extraction from the following formats:

Format Extension(s) Extractor Notes

7-Zip

.7z, .exe

SevenZipExtractor

Self-extracting archives, BCJ2 filter

CAB

.cab, .exe

CabExtractor

Self-extracting CAB, salvage mode

CPIO

.cpio

CpioExtractor

Old and new formats

GZIP

.gz, .tar.gz

GzipExtractor

Uses Ruby stdlib Zlib

MSI

.msi

OleExtractor

OLE compound document

RPM

.rpm

RpmExtractor

Extracts compressed payload

TAR

.tar

TarExtractor

Standard TAR format

XAR

.pkg, .xar

XarExtractor

macOS installer packages

XZ

.xz, .tar.xz, .txz

XzExtractor

Compound TAR+XZ support

ZIP

.zip

ZipExtractor

Standard ZIP format

All formats support recursive extraction for nested archives.

Architecture

Excavate follows a clean object-oriented architecture:

┌─────────────────────────────────────────────────────────────┐
│                     Excavate::Archive                       │
│           (Facade providing unified interface)              │
└───────────────────────────┬─────────────────────────────────┘
                            │
                            │ delegates to
                            │
    ┌───────────────────────┴───────────────────────┐
    │           Format Type Registry                │
    │           (TYPES hash mapping)                │
    └───────────────────────┬───────────────────────┘
                            │
                            │ instantiates
                            │
    ┌───────────────────────┴───────────────────────┐
    │           Extractors::Extractor               │
    │           (Abstract base class)               │
    └───────────────────────┬───────────────────────┘
                            │
                            │ specialized by
                            │
    ┌───────┬───────┬───────┼───────┬───────┬───────┐
    │       │       │       │       │       │       │
   Cab    Cpio    Gzip    Xar     Zip    SevenZip  ...
    │       │       │       │       │       │
    └───────┴───────┴───────┴───────┴───────┴───────┘
              Powered by Omnizip & Cabriolet

Design Principles

Single Responsibility

Each extractor handles one format

Open/Closed

New formats can be added without modifying existing code

Dependency Inversion

Archive class depends on Extractor abstraction

Part of the Omnizip Suite

Excavate is part of the Omnizip family of pure Ruby compression libraries:

Omnizip

Comprehensive compression library supporting 7z, ZIP, RAR4/5, TAR, ISO, XAR, RPM, OLE, XZ, GZIP, BZIP2, CPIO, and PAR2 formats with encryption and multi-volume support.

Cabriolet

Specialized library for Microsoft compression formats including CAB, CHM, SZDD, KWAJ, HLP, LIT, and OAB with full bidirectional support.

Excavate

Unified extraction interface built on Omnizip and Cabriolet, providing recursive extraction of nested archives.

Platform Support

Excavate is a pure Ruby gem with no compiled dependencies:

  • Ruby Implementations: MRI 2.7+, JRuby, TruffleRuby

  • Operating Systems: Linux, macOS, Windows, BSD

  • Special Handling: Windows file locking handled with automatic retries