本文目录导读:

我来教你用脚本整理音乐库,这里提供一个Python脚本方案,能自动处理常见问题:
基础整理脚本
#!/usr/bin/env python3
import os
import re
import shutil
import json
from pathlib import Path
import mutagen
from mutagen.easyid3 import EasyID3
from mutagen.mp3 import MP3
from mutagen.flac import FLAC
class MusicOrganizer:
def __init__(self, music_dir):
self.music_dir = Path(music_dir)
self.organized_dir = self.music_dir / "已整理"
def get_audio_metadata(self, file_path):
"""读取音频文件元数据"""
try:
ext = file_path.suffix.lower()
if ext == '.mp3':
audio = EasyID3(file_path)
return {
'artist': audio.get('artist', [''])[0],
'album': audio.get('album', [''])[0],
'title': audio.get('title', [''])[0],
'tracknumber': audio.get('tracknumber', [''])[0]
}
elif ext == '.flac':
audio = FLAC(file_path)
return {
'artist': audio.get('artist', [''])[0],
'album': audio.get('album', [''])[0],
'title': audio.get('title', [''])[0],
'tracknumber': audio.get('tracknumber', [''])[0]
}
except Exception as e:
print(f"读取 {file_path} 元数据失败: {e}")
return None
def sanitize_filename(self, name):
"""清理文件名中的非法字符"""
# 替换不合法字符
illegal_chars = r'[<>:"/\\|?*]'
return re.sub(illegal_chars, '_', name).strip()
def organize_by_artist_album(self):
"""按 艺术家/专辑 结构整理"""
if not self.music_dir.exists():
print("音乐目录不存在!")
return
# 创建整理目录
self.organized_dir.mkdir(exist_ok=True)
# 遍历所有音频文件
audio_exts = {'.mp3', '.flac', '.wav', '.m4a', '.ogg'}
moved_files = 0
for file_path in self.music_dir.rglob('*'):
if file_path.suffix.lower() not in audio_exts:
continue
metadata = self.get_audio_metadata(file_path)
# 如果没有元数据,使用文件名推测
if metadata is None or not metadata['artist']:
artist = '未知艺术家'
album = '未知专辑'
else:
artist = self.sanitize_filename(metadata['artist'])
album = self.sanitize_filename(metadata['album'] or '未知专辑')
# 构建目标路径
target_dir = self.organized_dir / artist / album
target_dir.mkdir(parents=True, exist_ok=True)
# 重命名文件(添加序号)
filename = file_path.name
if metadata and metadata['tracknumber']:
try:
track_num = int(re.search(r'\d+', metadata['tracknumber']).group())
filename = f"{track_num:02d} - {self.sanitize_filename(metadata['title'] or file_path.stem)}{file_path.suffix}"
except:
pass
# 处理重名
target_file = target_dir / filename
if target_file.exists():
base = target_file.stem
target_file = target_dir / f"{base}_1{target_file.suffix}"
# 移动文件
try:
shutil.move(str(file_path), str(target_file))
moved_files += 1
print(f"✓ {file_path.name} → {artist}/{album}/{filename}")
except Exception as e:
print(f"✗ 移动 {file_path} 失败: {e}")
print(f"\n完成!共整理 {moved_files} 个文件")
def fix_missing_tags(self):
"""智能修复文件名中的元数据"""
# 从文件名提取信息: 艺术家 - 专辑 - 曲目号 歌曲名.mp3
pattern = r'(.+?)\s*-\s*(.+?)\s*-\s*(\d+)\s*(.+)'
for file_path in self.music_dir.rglob('*.mp3'):
match = re.match(pattern, file_path.stem)
if match and not self.get_audio_metadata(file_path):
artist, album, track, title = match.groups()
try:
audio = EasyID3(file_path)
audio['artist'] = artist.strip()
audio['album'] = album.strip()
audio['title'] = title.strip()
audio['tracknumber'] = track.strip()
audio.save()
print(f"修复标签: {file_path.name}")
except Exception as e:
print(f"修复失败 {file_path.name}: {e}")
def generate_playlist(self):
"""生成通过播放列表"""
# 按流派分类
genres = {}
for file_path in self.organized_dir.rglob('*.mp3'):
try:
audio = EasyID3(file_path)
genre = audio.get('genre', ['未知'])[0]
if genre not in genres:
genres[genre] = []
genres[genre].append(str(file_path))
except:
pass
# 生成M3U播放列表
playlist_dir = self.music_dir / '播放列表'
playlist_dir.mkdir(exist_ok=True)
for genre, files in genres.items():
playlist_file = playlist_dir / f"{genre}.m3u"
with open(playlist_file, 'w', encoding='utf-8') as f:
f.write("#EXTM3U\n")
for file_path in files:
f.write(f"#EXTINF:{Path(file_path).stat().st_size // 1000},{Path(file_path).stem}\n")
f.write(f"{file_path}\n")
print(f"生成播放列表: {genre}.m3u ({len(files)}首)")
# 使用示例
if __name__ == "__main__":
# 使用方法:
# python music_organizer.py /path/to/music
import sys
if len(sys.argv) < 2:
print("用法: python music_organizer.py <音乐文件夹路径>")
sys.exit(1)
organizer = MusicOrganizer(sys.argv[1])
print("选择操作方式:")
print("1. 按艺术家/专辑整理")
print("2. 修复缺失的标签")
print("3. 生成播放列表")
print("4. 全部执行")
choice = input("输入选择 (1-4): ")
if choice in ['1', '4']:
organizer.organize_by_artist_album()
if choice in ['2', '4']:
organizer.fix_missing_tags()
if choice in ['3', '4']:
organizer.generate_playlist()
高级功能版本
如果你想处理更复杂的情况,这里有个增强版:
# 增强功能
def advanced_functions(self):
"""高级整理功能"""
# 1. 去重功能
def find_duplicates(self):
"""根据文件大小和MD5查找重复音乐"""
import hashlib
seen_files = {}
duplicates = []
for file_path in self.music_dir.rglob('*'):
if file_path.suffix.lower() not in ['.mp3', '.flac', '.wav']:
continue
# 计算文件哈希
file_hash = hashlib.md5(file_path.read_bytes()).hexdigest()
if file_hash in seen_files:
duplicates.append((seen_files[file_hash], file_path))
else:
seen_files[file_hash] = file_path
return duplicates
# 2. 批量重命名
def batch_rename(self):
"""批量重命名文件,统一格式"""
for file_path in self.music_dir.rglob('*'):
if file_path.suffix.lower() not in ['.mp3', '.flac']:
continue
# 智能识别格式并规范化
# 01-song.mp3 → 01_song.mp3
# artist-album-track.mp3 → 艺术家-专辑-01 歌曲名.mp3
pass # 实现你的重命名逻辑
# 3. 封面管理
def manage_covers(self):
"""下载和嵌入封面"""
import requests
cover_dir = self.music_dir / 'covers'
cover_dir.mkdir(exist_ok=True)
# 对没有封面的专辑下载封面
# 可以使用 iTunes API 或 Last.fm API
pass
# 4. 格式转换
def convert_formats(self):
"""批量格式转换(如flac转mp3)"""
import subprocess
for flac_file in self.music_dir.rglob('*.flac'):
mp3_file = flac_file.with_suffix('.mp3')
# 使用 ffmpeg 转换
subprocess.run([
'ffmpeg', '-i', str(flac_file),
'-codec:a', 'libmp3lame',
'-qscale:a', '2',
str(mp3_file)
])
使用方法
-
安装依赖:
pip install mutagen
-
基础使用:
python music_organizer.py ~/Music
-
高级使用(可添加到crontab定期执行):
# 每周日晚上整理 0 20 * * 0 python /path/to/music_organizer.py ~/Music
注意事项
- 备份原始文件:整理前务必备份,脚本会移动文件
- 测试运行:先在小目录测试,确认无误后再处理完整音乐库
- 保留原文件:修改脚本中的
shutil.move为shutil.copy即可保留原文件 - 处理特殊情况:歌手"Various Artists"、日本艺名、多艺术家合作等特殊场景需要额外处理
这个脚本基本能满足大部分整理需求,如果需要修改特定行为,告诉我你的具体需求,我可以提供定制版本。