API Reference
Constructor
Excavate::Archive.new(archive_path)- Parameters
archive_path-
Path to the archive file. Can be a string path, Pathname, or any object responding to
original_filename(e.g., Rails uploaded files). - Returns
-
A new
Excavate::Archiveinstance. - Example
# String path
archive = Excavate::Archive.new("package.zip")
# Pathname
archive = Excavate::Archive.new(Pathname.new("package.zip"))
# Rails upload
archive = Excavate::Archive.new(params[:file])Instance Methods
extract
Extract the archive to a target directory.
extract(target = nil, recursive_packages: false, files: [], filter: nil)- Parameters
target-
(optional) Target directory path. If omitted, creates a directory with the archive’s base name in the current directory.
recursive_packages-
(optional) Boolean. When
true, recursively extracts nested archives. Default:false. NOTE: Automatically set totruewhenfiles:option is provided. files-
(optional) Array of file paths to extract. If specified, only these files are extracted. Enables
recursive_packagesautomatically. filter-
(optional) Glob pattern string. If specified, only matching files are extracted.
- Returns
-
-
String: Target directory path (when extracting all)
-
Array<String>: Extracted file paths (when using
filesorfilter)
-
- Raises
TargetExistsError-
Target file or directory already exists.
TargetNotEmptyError-
Target directory is not empty.
TargetNotFoundError-
Specified file or pattern not found.
UnknownArchiveError-
Archive format not recognized.
- Examples
# Basic extraction
Excavate::Archive.new("package.zip").extract
# => "/path/to/package"
# Extract to specific directory
Excavate::Archive.new("package.zip").extract("/tmp/output")
# => "/tmp/output"
# Recursive extraction
Excavate::Archive.new("installer.msi").extract(recursive_packages: true)
# Selective extraction
Excavate::Archive.new("data.tar").extract(files: ["config.json"])
# => ["/path/to/config.json"]
# Multi-level nested extraction (recursive_packages auto-enabled)
Excavate::Archive.new("bundle.zip").extract(
files: ["level1.zip/level2.zip/file.txt"]
)
# => ["/path/to/file.txt"]
# Filter-based extraction
Excavate::Archive.new("fonts.zip").extract(filter: "**/*.ttf")
# => ["/path/to/Arial.ttf", "/path/to/Verdana.ttf"]files
Extract and process files through a block.
files(recursive_packages: false, files: [], filter: nil, &block)- Parameters
-
Same as
extract. Note thatrecursive_packagesis automatically enabled whenfiles:option is provided. - Block
-
Yields each extracted file path to the block.
- Returns
-
Array of values returned by the block.
- Behavior
-
-
Creates a temporary directory
-
Extracts files based on parameters
-
Yields each file path to the block
-
Cleans up temporary directory (Windows-safe)
-
Returns array of block results
-
- Example
# Collect font paths
font_paths = Excavate::Archive.new("fonts.zip").files(
filter: "**/*.ttf"
) do |path|
puts "Found: #{path}"
path
end
# => ["/tmp/.../Arial.ttf", "/tmp/.../Verdana.ttf"]
# Analyze files
stats = Excavate::Archive.new("data.tar.gz").files do |path|
{ path: path, size: File.size(path) }
end
# Process with recursive extraction
configs = Excavate::Archive.new("installer.msi").files(
recursive_packages: true,
filter: "**/*.conf"
) do |path|
{ name: File.basename(path), content: File.read(path) }
endSupported Formats
The TYPES constant maps extensions to extractors:
{
"cab" => Extractors::CabExtractor, # Microsoft Cabinet
"cpio" => Extractors::CpioExtractor, # Unix CPIO
"exe" => Extractors::SevenZipExtractor, # Self-extracting (7z or CAB)
"gz" => Extractors::GzipExtractor, # GZIP compression
"msi" => Extractors::OleExtractor, # Windows Installer
"pkg" => Extractors::XarExtractor, # macOS Package
"rpm" => Extractors::RpmExtractor, # Red Hat Package
"tar" => Extractors::TarExtractor, # Unix TAR
"xz" => Extractors::XzExtractor, # XZ compression
"zip" => Extractors::ZipExtractor # ZIP archive
}Format Detection
Format is detected by file extension, not content. Ensure files have correct extensions for proper extraction.
For .gz files, Excavate additionally verifies the gzip magic bytes to avoid extracting non-gzip files with .gz extension.
For .exe files, Excavate tries 7-Zip first, then falls back to CAB extraction for self-extracting CAB archives.
Error Classes
All errors inherit from Excavate::Error.
Excavate::Error
Base error class for all Excavate errors.
begin
# ... extraction code
rescue Excavate::Error => e
puts "Extraction failed: #{e.message}"
endExcavate::TargetExistsError
Raised when the target file or directory already exists.
begin
Excavate::Archive.new("file.zip").extract
rescue Excavate::TargetExistsError => e
puts e.message # "Target file `file` already exists."
endExcavate::TargetNotEmptyError
Raised when the target directory is not empty.
begin
Excavate::Archive.new("file.zip").extract("/non/empty/dir")
rescue Excavate::TargetNotEmptyError => e
puts e.message # "Target directory `dir` is not empty."
endExcavate::TargetNotFoundError
Raised when a specified file or filter pattern matches nothing.
# Missing file
begin
Excavate::Archive.new("data.zip").extract(files: ["missing.txt"])
rescue Excavate::TargetNotFoundError => e
puts e.message # "File `missing.txt` not found."
end
# No filter match
begin
Excavate::Archive.new("data.zip").extract(filter: "*.pdf")
rescue Excavate::TargetNotFoundError => e
puts e.message # "Filter `*.pdf` matched no file."
endExtractor Classes
Internal classes for format-specific extraction. Not typically used directly.
Base Class
class Extractors::Extractor
def initialize(archive)
@archive = archive
end
def extract(target)
raise NotImplementedError
end
endFormat-Specific Extractors
Each extractor implements the same interface:
Extractors::CabExtractor.new(archive).extract(target)
Extractors::CpioExtractor.new(archive).extract(target)
Extractors::GzipExtractor.new(archive).extract(target)
Extractors::OleExtractor.new(archive).extract(target)
Extractors::RpmExtractor.new(archive).extract(target)
Extractors::SevenZipExtractor.new(archive).extract(target)
Extractors::TarExtractor.new(archive).extract(target)
Extractors::XarExtractor.new(archive).extract(target)
Extractors::XzExtractor.new(archive).extract(target)
Extractors::ZipExtractor.new(archive).extract(target)Extractor Details
CabExtractor
-
Uses Cabriolet gem
-
Enables salvage mode for checksum error tolerance
-
Handles self-extracting CAB archives
Helper Classes
Excavate::FileMagic
Detects file format by reading magic bytes.
# Class method
format = Excavate::FileMagic.detect("archive.cab")
# => :cab
# Instance method
magic = Excavate::FileMagic.new("file.gz")
format = magic.detect
# => :gzipSupported formats:
| Format | Magic Bytes | Return Value |
|---|---|---|
CAB |
|
|
XZ |
|
|
GZIP |
|
|
Unknown | - |
|
Platform-Specific Behavior
Windows File Locking
Excavate handles Windows file locking with automatic retries:
-
Maximum 5 retries with 0.2 second delays
-
Handles
Errno::EACCESandErrno::ENOTEMPTY -
Falls back to copying files if deletion fails
This ensures reliable operation on Windows where files may be temporarily locked by other processes or the system.