Last active
May 29, 2025 17:58
-
-
Save jmatthewturner/32a84e2f45e5fe8dbe7a738ac6ca5ffd to your computer and use it in GitHub Desktop.
BASH script for stripping hidden fields from id3 tags.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This script was written entirely by Claude.ai, with prompts by jmatthewturner. | |
# It does what I need well enough, so I'm not taking the time to refine it. | |
# But I still wanted to share in case anyone else finds it useful. | |
# | |
# It's purpose is to strip hidden fields from id3 tags, as part of a larger | |
# project to get a Kenwood Excelon head unit working properly with USB MP3s. | |
# Details of the larger project are here: | |
# https://jmatthewturner.wordpress.com/2025/05/29/usb-mp3-functionality-on-kenwood-excelon-head-units/ | |
# | |
# Known issue: Sometimes, for reasons I have not investigated, it renames | |
# the artist as “[artist] album [artist]”; i.e., the Artist field goes | |
# from “Metallica” to “Metallica album Metallica.” Probably a delimiter | |
# issue, but I don't see the problem at first glance, and I’ve spent | |
# enough time on this already. As it happens, the fix is just to run | |
# the script again, and it fixes the issue on the second pass. Go figure. | |
# | |
# https://gist.github.com/jmatthewturner/32a84e2f45e5fe8dbe7a738ac6ca5ffd | |
# | |
# Everything after this line is AI generated. -JMT | |
# Script to rebuild MP3 tags in ID3v2.3 format with comprehensive year handling | |
# This script removes all tags and rebuilds them to eliminate problematic UserTextFrames | |
echo "This script will remove all ID3 tags and rebuild them in ID3v2.3 format." | |
echo "It will retain title, artist, album, year, and track number information." | |
echo "Are you sure you want to continue? (y/n)" | |
read confirm | |
if [[ ! "$confirm" =~ ^[Yy] ]]; then | |
echo "Operation cancelled." | |
exit 0 | |
fi | |
# Make a backup directory | |
backup_dir="./tag_backup_$(date +%Y%m%d_%H%M%S)" | |
mkdir -p "$backup_dir" | |
echo "Created backup directory: $backup_dir" | |
# Counter for processed files | |
count=0 | |
# Process each MP3 file | |
for file in *.mp3; do | |
# Skip if no MP3 files found | |
if [ "$file" = "*.mp3" ]; then | |
echo "No MP3 files found in the current directory." | |
exit 1 | |
fi | |
echo "Processing: $file" | |
# Extract and save current tag information | |
echo "Extracting tag information..." | |
title=$(eyeD3 "$file" | grep "title:" | sed -e 's/title: //') | |
artist=$(eyeD3 "$file" | grep "artist:" | sed -e 's/artist: //') | |
album=$(eyeD3 "$file" | grep "album:" | sed -e 's/album: //') | |
year=$(eyeD3 "$file" | grep "recording date:" | sed -e 's/recording date: //') | |
track=$(eyeD3 "$file" | grep "track:" | sed -e 's/track: //' | awk '{print $1}') | |
#eyeD3 --write-images=. "$file" | |
# Save tag info to backup file | |
tag_info="$backup_dir/${file%.mp3}.tags" | |
echo "File: $file" > "$tag_info" | |
echo "Title: $title" >> "$tag_info" | |
echo "Artist: $artist" >> "$tag_info" | |
echo "Album: $album" >> "$tag_info" | |
echo "Year: $year" >> "$tag_info" | |
echo "Track: $track" >> "$tag_info" | |
echo "Saved tag backup to $tag_info" | |
# Remove all ID3 tags using id3v2 if available, otherwise eyeD3 | |
echo "Removing all ID3 tags..." | |
if command -v id3v2 &> /dev/null; then | |
id3v2 --delete-all "$file" | |
else | |
eyeD3 --remove-all "$file" | |
fi | |
# Add tags back with ID3v2.3 format and proper year handling | |
echo "Adding tags back in ID3v2.3 format..." | |
eyeD3 --to-v2.3 \ | |
--title="$title" \ | |
--artist="$artist" \ | |
--album="$album" \ | |
--release-date="$year" \ | |
--recording-date="$year" \ | |
--orig-release-date="$year" \ | |
--track="$track" \ | |
"$file" | |
# Set the TYER frame as well for maximum compatibility | |
if command -v id3v2 &> /dev/null; then | |
id3v2 --TYER "$year" "$file" | |
fi | |
#if [ -f "FRONT_COVER.jpg" ]; then | |
# echo "FRONT_COVER.jpg successfully extracted from $file." | |
# cover_img="FRONT_COVER.jpg" | |
#elif [ -f "FRONT_COVER.png" ]; then | |
# echo "FRONT_COVER.png successfully extracted from $file." | |
# cover_img="FRONT_COVER.png" | |
# else | |
# # At this point, all attempts to locate artwork have failed. | |
# echo "No cover image found!" | |
#fi | |
# Re-embed cover art | |
#eyeD3 -Q --add-image "$cover_img:FRONT_COVER" "$file" | |
# Verify the tags | |
echo "Verifying tags..." | |
eyeD3 "$file" | grep -E "title:|artist:|album:|recording date:|track:" | |
# Check if UserTextFrames are still present | |
if eyeD3 "$file" | grep -q "UserTextFrame:"; then | |
echo "WARNING: UserTextFrames still present in $file after removal." | |
else | |
echo "SUCCESS: No UserTextFrames detected in $file" | |
fi | |
# Increment counter | |
((count++)) | |
echo "Completed: $file" | |
echo "----------------------------" | |
done | |
echo "Complete! Processed $count files." | |
echo "Tag information was backed up to: $backup_dir" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment