A robust Bash script for converting CD/DVD disc images and archives into CHD (Compressed Hunks of Data) format using chdman.
Designed for batch processing, validation, logging, and multi-disc handling โ ideal for emulation libraries.
Convert everything in a directory:
./chdtool.sh -r /path/to/roms- ๐ฆ Supports common input formats:
- Archives:
zip,rar,7z - Disc images:
iso,cue,gdi,ccd
- Archives:
- ๐ Automatic extraction of archives before conversion
- ๐ฟ Intelligent CD vs DVD detection (
createcdvscreatedvd) - โ
Verification of CHDs using
chdman verify- Automatic retry on failure
- Deletes invalid CHDs
- ๐ Space savings reporting
- ๐งพ Automatic M3U generation for multi-disc sets
- ๐งน Safe temp directory handling with cleanup traps
- ๐งช Dry-run mode (no changes made)
- ๐ชต Structured logging system:
- Console / file / syslog / journald
- Configurable verbosity
- โก Progress bar (TTY-aware, non-spammy)
./chdtool.sh [options] <input directory>| Option | Description |
|---|---|
-k, --keep-originals |
Do not delete source files after conversion |
-r, --recursive |
Process subdirectories |
-n, --dry-run |
Show what would happen without making changes |
-F, --file-tee |
Force logging to file |
-N, --no-file-tee |
Disable logging to file |
./chdtool.sh -r /mnt/romsDry run:
./chdtool.sh -n /mnt/roms.iso.cue(with referenced BIN/WAV/MP3 validation).gdi.ccd
.zip.rar.7z
Archives are extracted to a temporary directory and processed automatically.
- CHDs are created alongside the input files
- Temporary files use
.tmpsuffix until verified - Originals are removed unless
--keep-originalsis set
- Automatically detects disc numbering patterns:
Disc 1,CD2,Part 3,Side A,1 of 2, etc.
- Generates
.m3uplaylists when 2+ discs are detected - Filenames are sanitized for cross-platform compatibility
Example:
Final Fantasy VII (Disc 1).chd
Final Fantasy VII (Disc 2).chd
Final Fantasy VII.m3u
- All CHDs are verified with
chdman verify - Failed verification:
- Retried once
- Deleted if still invalid
- Existing CHDs are verified before skipping conversion
Configurable via environment variables:
LOG_DEST=auto|console|file|syslog|journald
LOG_LEVEL_THRESHOLD=DEBUG|INFO|WARN|ERROR
LOG_TEE_CONSOLE=auto|1|0
LOG_TEE_FILE=1|0
LOG_TAG=chdtoolDefault log file:
logs/chd_conversion_<timestamp>.log
At the end of a run:
- Total original size
- Total CHD size
- Space saved
- Archives processed
- CHDs created
- Failures
- Elapsed time
The following tools must be installed:
chdmanunzipunrar7zstatawk
Optional (enhancements):
file(better ISO detection)perl(improved filename parsing)uconv(Unicode normalization)systemd-cat/logger(logging backends)
Use --dry-run to preview actions:
./chdtool.sh -n /roms- No files are created, moved, or deleted
- All intended operations are logged
- DVD support requires a version of
chdmanwithcreatedvd - CUE files referencing missing files will fail validation
- Temporary files are cleaned automatically, even on interruption
- Safe by default (verify before replace)
- Idempotent (re-runs donโt duplicate work)
- Transparent logging
- Minimal dependencies
- Works well on large ROM collections
- Parallel processing
- Better metadata integration
- Optional compression tuning
- Integration with tools like Retromount / ROM managers