Python读取MP3标签按歌手专辑分类移动文件报错求助
MP3文件按歌手专辑分类移动时的WinError 123错误修复
问题场景
尝试用Python读取指定目录下MP3文件的ID3标签,按歌手和专辑分类移动到新目录,但运行代码时触发WinError 123错误,提示文件名/目录名语法错误。
原代码
import os import shutil from mutagen.easyid3 import EasyID3 # Set the source and destination directories source_dir = "E:\Radio Metaverse\Songs\Greatest Hits" destination_dir = "/sorted" # Walk through the directory tree and find all mp3 files for root, dirs, files in os.walk(source_dir): for file in files: if file.endswith(".mp3"): # Use Mutagen to extract the artist and album tags mp3_path = os.path.join(root, file) tags = EasyID3(mp3_path) artist = tags.get("artist", ["Unknown Artist"])[0] album = tags.get("album", ["Unknown Album"])[0] # Create directories for the artist and album if they don't exist artist_dir = os.path.join(destination_dir, artist) if not os.path.exists(artist_dir): os.makedirs(artist_dir) album_dir = os.path.join(artist_dir, album) if not os.path.exists(album_dir): os.makedirs(album_dir) # Move the mp3 file to the album directory destination_path = os.path.join(album_dir, file) shutil.move(mp3_path, destination_path) print("Done!")
错误信息
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: sorted/Joe Walsh\\Confessions. 'OSError:' is not recognized as an internal or external command,
错误原因及修复步骤
1. 路径格式问题
Windows系统使用反斜杠\作为路径分隔符,原代码中:
- 源路径未加
r前缀,导致\S这类字符被当作转义序列解析错误 - 目标目录用了Unix风格的
/sorted,Windows无法识别这种相对路径格式
修复:
给路径添加r前缀(raw字符串)避免转义,同时改用Windows兼容的路径格式:
source_dir = r"E:\Radio Metaverse\Songs\Greatest Hits" destination_dir = r"E:\Radio Metaverse\Songs\sorted" # 绝对路径 # 或者用相对路径:destination_dir = r".\sorted"
2. MP3标签含非法字符
歌手或专辑名称可能包含Windows文件名禁止的字符(比如\ / : * ? " < > |),导致创建目录时触发语法错误。
修复:
添加清理非法字符的函数,处理标签内容:
def clean_filename(name): invalid_chars = '<>:"/\\|?*' for char in invalid_chars: name = name.replace(char, '') return name.strip()
获取标签后调用该函数:
artist = clean_filename(tags.get("artist", ["Unknown Artist"])[0]) album = clean_filename(tags.get("album", ["Unknown Album"])[0])
3. 目录创建逻辑优化
用os.makedirs(..., exist_ok=True)替代手动判断目录是否存在,简化代码同时避免竞态条件:
artist_dir = os.path.join(destination_dir, artist) os.makedirs(artist_dir, exist_ok=True) album_dir = os.path.join(artist_dir, album) os.makedirs(album_dir, exist_ok=True)
修复后的完整代码
import os import shutil from mutagen.easyid3 import EasyID3 def clean_filename(name): invalid_chars = '<>:"/\\|?*' for char in invalid_chars: name = name.replace(char, '') return name.strip() # 修正路径格式,使用raw字符串避免转义 source_dir = r"E:\Radio Metaverse\Songs\Greatest Hits" # 目标目录改为Windows格式的绝对路径 destination_dir = r"E:\Radio Metaverse\Songs\sorted" for root, dirs, files in os.walk(source_dir): for file in files: if file.lower().endswith(".mp3"): # 兼容大小写后缀 mp3_path = os.path.join(root, file) try: tags = EasyID3(mp3_path) artist = clean_filename(tags.get("artist", ["Unknown Artist"])[0]) album = clean_filename(tags.get("album", ["Unknown Album"])[0]) except Exception as e: # 处理标签读取失败的文件,归类到未知目录 print(f"读取{mp3_path}标签失败: {e}") artist = "Unknown Artist" album = "Unknown Album" artist_dir = os.path.join(destination_dir, artist) os.makedirs(artist_dir, exist_ok=True) album_dir = os.path.join(artist_dir, album) os.makedirs(album_dir, exist_ok=True) destination_path = os.path.join(album_dir, file) # 避免同名文件覆盖 if os.path.exists(destination_path): name, ext = os.path.splitext(file) counter = 1 while os.path.exists(os.path.join(album_dir, f"{name}_{counter}{ext}")): counter += 1 destination_path = os.path.join(album_dir, f"{name}_{counter}{ext}") shutil.move(mp3_path, destination_path) print("Done!")
额外说明
- 增加
try-except块处理标签读取失败的文件,避免程序崩溃 - 兼容
.MP3这类大写后缀的文件 - 处理目标目录中已存在的同名文件,自动添加数字后缀避免覆盖
内容的提问来源于stack exchange,提问作者Radio Metaverse
相关产品推荐
相关产品推荐

