Skip to content

Instantly share code, notes, and snippets.

@BenMcLean
Last active November 2, 2025 23:58
Show Gist options
  • Select an option

  • Save BenMcLean/be7cf1c25cb71647d0547ef2bc2f5950 to your computer and use it in GitHub Desktop.

Select an option

Save BenMcLean/be7cf1c25cb71647d0547ef2bc2f5950 to your computer and use it in GitHub Desktop.
Use mame-tools chdman to mass convert WAV/BIN/cue CD images to CHD format
#!/bin/bash
# Check if directory argument provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <directory>"
echo "Example: $0 /path/to/psx"
exit 1
fi
TARGET_DIR="$1"
# Check if directory exists
if [ ! -d "$TARGET_DIR" ]; then
echo "Error: Directory does not exist: $TARGET_DIR"
exit 1
fi
# Function to format seconds into human-readable time
format_time() {
local seconds=$1
local hours=$((seconds / 3600))
local minutes=$(((seconds % 3600) / 60))
local secs=$((seconds % 60))
if [ $hours -gt 0 ]; then
printf "%dh %dm %ds" $hours $minutes $secs
elif [ $minutes -gt 0 ]; then
printf "%dm %ds" $minutes $secs
else
printf "%ds" $secs
fi
}
echo "Converting CD images to CHD in: $TARGET_DIR"
echo "================================================"
echo ""
# Count total CUE files
echo "Scanning for CUE files..."
total_files=$(find "$TARGET_DIR" -type f -iname "*.cue" | wc -l)
if [ $total_files -eq 0 ]; then
echo "No CUE files found in $TARGET_DIR"
exit 0
fi
echo "Found $total_files CUE file(s) to convert"
echo ""
# Counter for statistics
current=0
total_converted=0
total_failed=0
# Start time
start_time=$(date +%s)
# Find all .cue files
find "$TARGET_DIR" -type f -iname "*.cue" | sort | while read -r cuefile; do
((current++))
dirname=$(dirname "$cuefile")
basename=$(basename "$cuefile" .cue)
chdfile="${dirname}/${basename}.chd"
# Calculate progress percentage
progress=$((current * 100 / total_files))
# Calculate time estimates
current_time=$(date +%s)
elapsed=$((current_time - start_time))
if [ $current -gt 1 ]; then
avg_time_per_file=$((elapsed / (current - 1)))
remaining_files=$((total_files - current + 1))
eta=$((avg_time_per_file * remaining_files))
eta_formatted=$(format_time $eta)
elapsed_formatted=$(format_time $elapsed)
else
eta_formatted="calculating..."
elapsed_formatted=$(format_time $elapsed)
fi
# Progress bar with standard ASCII characters
bar_width=30
filled=$((progress * bar_width / 100))
empty=$((bar_width - filled))
bar=$(printf "%${filled}s" | tr ' ' '#')
bar+=$(printf "%${empty}s" | tr ' ' '-')
echo "[$bar] $progress% ($current/$total_files)"
echo "Elapsed: $elapsed_formatted | ETA: $eta_formatted"
echo "Converting: $basename"
echo "---"
# Convert to CHD (show all output)
if chdman createcd -i "$cuefile" -o "$chdfile"; then
echo "---"
echo "✓ Successfully converted: $basename"
# Parse cue file for referenced files and collect them
cue_dir=$(dirname "$cuefile")
files_to_delete=()
# Add the cue file itself
files_to_delete+=("$cuefile")
# Parse cue file for referenced files (BIN, WAV, ISO, etc.)
while IFS= read -r line; do
# Match FILE lines with quoted or unquoted filenames
if [[ $line =~ FILE[[:space:]]+\"([^\"]+)\" ]] || [[ $line =~ FILE[[:space:]]+([^[:space:]]+)[[:space:]] ]]; then
referenced_file="${BASH_REMATCH[1]}"
# Handle relative paths
full_path="${cue_dir}/${referenced_file}"
if [[ -f "$full_path" ]]; then
files_to_delete+=("$full_path")
fi
fi
done < "$cuefile"
# Delete all referenced files
for file in "${files_to_delete[@]}"; do
echo " Removing: $(basename "$file")"
rm -f "$file"
done
((total_converted++))
echo ""
else
echo "---"
echo "✗ Failed to convert: $basename"
echo " Skipping deletion of source files"
((total_failed++))
echo ""
fi
done
# Final statistics
end_time=$(date +%s)
total_time=$((end_time - start_time))
total_time_formatted=$(format_time $total_time)
echo "================================================"
echo "Conversion complete!"
echo "Total time: $total_time_formatted"
echo ""
@BenMcLean
Copy link
Author

This command will change the owner of all the CHDs:

sudo find /path/to/directory -type f -name "*.chd" -exec chown 1001:1001 {} +

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment