acgdp recursively extracts ZIP, 7z, and RAR archives. It recognizes archives by their contents, including files renamed to .jpg or .png and valid images with an archive appended. After each extraction, it checks every resulting file for another archive.
The project's own code is licensed under Apache-2.0. RAR support embeds UnRAR code through unrar-ng; its separate terms and restrictions are in the UnRAR license.
Rust 1.89 or newer is required to build:
cargo build --releaseRun acgdp without arguments to display the full command help.
Extract a file:
acgdp game.jpg --ask-passwordBy default, this creates game.jpg.extracted beside the input. The original game.jpg stays untouched. On success, nested archive files are removed and their contents are placed in the directories where those archives appeared. Common options:
acgdp game.jpg -o ./game --ask-password
acgdp game.jpg -p 'shared-password' --keep-intermediates
acgdp game.jpg --max-depth 64 --max-gib 50
acgdp game.jpg --color always
acgdp game.jpg --jobs 1
acgdp game.7z.001 --ask-password-p is useful in scripts, but the password may appear in process arguments. Use --ask-password for an interactive Chinese prompt with same-line masked input. The mask is colored when terminal color is enabled. The number of mask characters reveals the password length while typing; the completed prompt displays a fixed number of asterisks. Unencrypted archives need no password.
Help, extraction progress, and errors use color in a terminal. Progress shows each layer's number, format, and archive name, followed by the output location, total bytes written, and elapsed time. In an interactive terminal, ZIP and 7z layers show separate byte progress bars based on their declared uncompressed sizes; RAR layers show an activity indicator and bytes written because a reliable total is not available during extraction. These are per-layer indicators, not an overall percentage. Redirected output has plain lines without animated progress. Set --color always to keep colors when redirecting output, or --color never to disable them; auto is the default.
By default, --jobs 2 passes completed inner archives to the next worker at every nesting level, allowing multiple layers to overlap. When a 7z member contains a non-solid RAR, the next layer can extract complete RAR entries while that member is still being written. Other format combinations start after the inner file is complete. Use --jobs 1 for the serial path. --jobs 2 enables the pipeline and may create a stage at each nested level; it does not cap the process at two threads. The speedup depends on the archive layout and storage device.
For RAR members up to 1 MiB, the pipeline reuses decoded bytes to look for another archive. This avoids rereading large numbers of small files immediately after writing them. It still checks each file's full contents, including archives hidden inside images.
- Takes one input file and ignores its extension. ZIP and 7z use Rust libraries; RAR uses
unrar-ng, which includes RARLAB's UnRAR C/C++ code. - For a split 7z archive, pass the
.001file and keep.002,.003, and later parts beside it. The parts are read as one archive without creating a joined copy. - Extracts to a temporary directory and creates the final output directory only after every nested layer succeeds. A failure leaves the original input intact and no partial output directory.
- Refuses to overwrite an existing output directory or a file with the same name. It also rejects archive entries with escaping paths or symbolic links.
- Extracts at most 32 layers and writes at most 20 GiB across all layers by default. ZIP and 7z are limited as bytes are written. RAR entry sizes are checked before extraction and the written sizes are checked afterward.
- Multipart RAR archives are not handled specially yet. Encrypted RAR headers and unusual compression methods need more testing with real files.
cargo build
python tests/smoke.py
cargo bench --bench nested_extraction -- --noplotThe smoke test covers nested ZIPs, ZIP/7z/RAR appended to images, RAR3/RAR5, encrypted ZIP/7z, and cleanup on failure. The 7z and encrypted ZIP cases require 7-Zip installed locally; the other tests do not. Two RAR fixtures in tests/fixtures come from RAR Test Files under CC0. A RAR fixture used to check symbolic link rejection comes from the libarchive test suite.
The Criterion benchmark compares --jobs 1 and --jobs 2 on generated ZIP fixtures with multiple inner archives, a single chain, and four nested layers. Use python tests/compare_pipeline.py <baseline> <candidate> to interleave runs of two binaries. See benchmark notes for the measured results and limits. The real split 7z→RAR5 sample is documented in sample validation and small-file detection optimization; results varied between runs, so speedups are not guaranteed.