Skip to content

Instantly share code, notes, and snippets.

@joeynotjoe
Created July 16, 2025 12:56
Show Gist options
  • Select an option

  • Save joeynotjoe/23dadb5f397ff650790bdd56a7e32b47 to your computer and use it in GitHub Desktop.

Select an option

Save joeynotjoe/23dadb5f397ff650790bdd56a7e32b47 to your computer and use it in GitHub Desktop.
Convert CHD to BIN/CUE
#!/usr/bin/env zsh
# CHD to BIN/CUE Converter
VERSION="1.1"
DEFAULT_EXTENSIONS=("chd")
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Help function
show_help() {
cat <<EOF
${GREEN}CHD to BIN/CUE Converter ${VERSION}${NC}
Usage: ${0:t} [options] [file|directory]
Options:
-h, --help Show this help message
-v, --version Show version information
-r, --recursive Process directories recursively (default)
-e, --ext Specify alternate extensions (comma-separated)
-q, --quiet Suppress non-error output
-d, --dry-run Show what would be done without actually converting
Examples:
${0:t} # Convert all CHD files in current directory
${0:t} /path/to/game.chd # Convert single file
${0:t} /path/to/directory # Convert all CHDs in directory
${0:t} -e gdi,chd # Convert both GDI and CHD files
EOF
}
# Initialize variables
QUIET=0
DRY_RUN=0
EXTENSIONS=($DEFAULT_EXTENSIONS)
TOTAL_FILES=0
SUCCESS_COUNT=0
FAIL_COUNT=0
START_TIME=$SECONDS
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_help
exit 0
;;
-v|--version)
echo "${0:t} version ${VERSION}"
exit 0
;;
-q|--quiet)
QUIET=1
shift
;;
-d|--dry-run)
DRY_RUN=1
shift
;;
-e|--ext)
EXTENSIONS=(${(s:,:)2})
shift 2
;;
-*)
echo "${RED}Error: Unknown option $1${NC}" >&2
show_help
exit 1
;;
*)
TARGET="$1"
shift
;;
esac
done
# Build find pattern
pattern="*.(${(j:|:)EXTENSIONS})"
# Find files
if [[ -n "$TARGET" ]]; then
if [[ -f "$TARGET" ]]; then
files=("$TARGET")
elif [[ -d "$TARGET" ]]; then
files=("$TARGET"/**/$~pattern)
else
echo "${RED}Error: '$TARGET' is neither a file nor directory${NC}" >&2
exit 1
fi
else
files=(**/$~pattern)
fi
TOTAL_FILES=${#files[@]}
# Exit if no files found
if [[ $TOTAL_FILES -eq 0 ]]; then
[[ $QUIET -eq 0 ]] && echo "${YELLOW}No files found with extensions: ${EXTENSIONS}${NC}"
exit 0
fi
# Processing function
process_file() {
local file="$1"
local dir="${file:r}"
local base="${file:t:r}"
local cue="${dir}.cue"
local bin="${dir}.bin"
[[ $QUIET -eq 0 ]] && echo "${BLUE}Processing: ${file}${NC}"
if [[ $DRY_RUN -eq 1 ]]; then
[[ $QUIET -eq 0 ]] && echo " [DRY RUN] Would create: ${dir}/{${base}.cue,${base}.bin}"
return 0
fi
# Create directory
if ! mkdir -p "$dir" 2>/dev/null; then
echo "${RED}Error: Failed to create directory ${dir}${NC}" >&2
return 1
fi
# Convert file
if chdman extractcd -i "$file" -o "$cue" -ob "$bin"; then
if mv "${cue}" "${bin}" "$dir/"; then
[[ $QUIET -eq 0 ]] && echo "${GREEN} Success: Created ${dir}/{${base}.cue,${base}.bin}${NC}"
return 0
else
echo "${RED} Error: Failed to move output files to ${dir}${NC}" >&2
return 1
fi
else
echo "${RED} Error: CHDMAN conversion failed for ${file}${NC}" >&2
# Clean up partial files
[[ -f "$cue" ]] && rm -f "$cue"
[[ -f "$bin" ]] && rm -f "$bin"
return 1
fi
}
# Main processing loop
for file in $files; do
if process_file "$file"; then
((SUCCESS_COUNT++))
else
((FAIL_COUNT++))
fi
done
# Summary
if [[ $QUIET -eq 0 ]]; then
echo "\n${BLUE}Conversion Summary:${NC}"
echo " Total files: $TOTAL_FILES"
echo " Successful: $SUCCESS_COUNT"
echo " Failed: $FAIL_COUNT"
echo " Time elapsed: $((SECONDS - START_TIME)) seconds"
fi
exit $((FAIL_COUNT > 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment