Basic Extraction
The simplest way to extract an archive:
require "excavate"
# Extract to auto-created directory
Excavate::Archive.new("package.zip").extract
# Creates ./package/ directory with contents
# Extract to specific directory
Excavate::Archive.new("package.zip").extract("/path/to/target")Recursive Extraction
Extract nested archives automatically. This is particularly useful for:
-
MSI installers containing CAB files
-
Self-extracting executables
-
Complex software distributions
-
macOS installer packages (PKG)
# Extract MSI and all nested CAB files
Excavate::Archive.new("installer.msi").extract(recursive_packages: true)
# Result: All files from MSI and nested CABs in target directoryHow Recursive Extraction Works
-
Extract the top-level archive
-
Scan extracted files for nested archives
-
Extract each nested archive
-
Replace archive with its contents
-
Repeat until no more nested archives found
Selective Extraction
Extract only specific files from an archive:
# Extract specific files by path
Excavate::Archive.new("data.tar.gz").extract(
files: ["config/settings.json", "data/users.csv"]
)
# Extract from nested archives
Excavate::Archive.new("package.msi").extract(
files: ["fonts.zip/Arial.ttf"],
recursive_packages: true
)If a specified file is not found, a TargetNotFoundError is raised.
Filter-Based Extraction
Extract files matching a glob pattern:
# Extract all TrueType fonts
Excavate::Archive.new("fonts.zip").extract(filter: "**/*.ttf")
# Extract configuration files
Excavate::Archive.new("backup.tar").extract(filter: "etc/**/*.conf")
# Extract multiple extensions
Excavate::Archive.new("assets.zip").extract(filter: "**/*.{png,jpg,svg}")File Iteration
Use the files method to process extracted files without managing directories:
# Collect all font files
fonts = Excavate::Archive.new("package.zip").files(
recursive_packages: true,
filter: "**/*.ttf"
) do |file_path|
puts "Found: #{file_path}"
file_path
end
puts "Total fonts: #{fonts.size}"The files method:
-
Creates a temporary directory
-
Extracts files based on parameters
-
Yields each file path to your block
-
Cleans up the temporary directory
-
Returns an array of block results
Working with Different Formats
Windows Installers (MSI)
MSI files are OLE compound documents containing CAB archives:
# Extract MSI and all embedded CABs
Excavate::Archive.new("setup.msi").extract(recursive_packages: true)
# MSI structure:
# setup.msi
# ├── data1.cab (extracted automatically)
# ├── data2.cab (extracted automatically)
# └── final filesSelf-Extracting Archives
EXE files may be 7-Zip or CAB self-extracting archives:
# Automatically detects format
Excavate::Archive.new("installer.exe").extract(recursive_packages: true)
# Falls back from 7z to CAB if neededRPM Packages
RPM files contain compressed CPIO payloads:
# Extract RPM package
Excavate::Archive.new("package.rpm").extract(recursive_packages: true)
# Extracts payload.cpio.gz automaticallyCommand-Line Interface
Excavate includes a CLI for quick extraction tasks:
# Basic extraction
excavate package.zip
# Recursive extraction
excavate --recursive installer.msi
# Extract specific files
excavate data.tar.gz config/settings.json
# Filter by pattern
excavate --filter "**/*.ttf" fonts.zip
# Combine options
excavate --recursive --filter "**/*.conf" package.msiSee CLI Reference for complete documentation.
Error Handling
Excavate provides specific error classes:
require "excavate"
begin
Excavate::Archive.new("archive.zip").extract("/existing/dir")
rescue Excavate::TargetNotEmptyError => e
puts "Directory not empty: #{e.message}"
rescue Excavate::TargetNotFoundError => e
puts "File not found: #{e.message}"
rescue Excavate::UnknownArchiveError => e
puts "Unsupported format: #{e.message}"
rescue Excavate::Error => e
puts "Extraction failed: #{e.message}"
endRails Integration
Excavate works with Rails uploaded files:
class UploadsController < ApplicationController
def upload
archive = Excavate::Archive.new(params[:file])
# Extract to temporary directory
target = Dir.mktmpdir
archive.extract(target, recursive_packages: true)
# Process extracted files
# ...
ensure
FileUtils.rm_rf(target)
end
endThe archive parameter accepts any object responding to original_filename.