本文目录导读:

我来介绍几种用脚本批量整理音乐文件的方法,主要使用Python和shell脚本。
Python脚本(最灵活)
基础整理脚本
import os
import shutil
import re
from pathlib import Path
import eyed3 # 需要安装:pip install eyed3
def organize_music(source_dir, dest_dir):
"""
按艺术家/专辑结构整理音乐文件
"""
# 支持的音频格式
audio_extensions = {'.mp3', '.flac', '.wav', '.m4a', '.ogg', '.wma'}
for root, dirs, files in os.walk(source_dir):
for file in files:
file_path = os.path.join(root, file)
ext = os.path.splitext(file)[1].lower()
if ext not in audio_extensions:
continue
try:
# 尝试读取ID3标签
audio_file = eyed3.load(file_path)
if audio_file and audio_file.tag:
artist = audio_file.tag.artist or "Unknown Artist"
album = audio_file.tag.album or "Unknown Album"
else:
artist, album = extract_info_from_filename(file)
except:
artist, album = extract_info_from_filename(file)
# 清理非法字符
artist = clean_filename(artist)
album = clean_filename(album)
# 创建目标目录
dest_path = os.path.join(dest_dir, artist, album)
os.makedirs(dest_path, exist_ok=True)
# 复制文件
shutil.copy2(file_path, os.path.join(dest_path, file))
print(f"已整理: {file} -> {artist}/{album}/")
def extract_info_from_filename(filename):
"""从文件名提取艺术家和专辑信息"""
# 示例格式: "Artist - Album - Song.mp3"
name = os.path.splitext(filename)[0]
parts = name.split(" - ")
if len(parts) >= 3:
return parts[0], parts[1]
else:
return "Unknown Artist", "Unknown Album"
def clean_filename(name):
"""清理文件名中的非法字符"""
# Windows不允许的字符
illegal_chars = r'[<>:"/\\|?*]'
return re.sub(illegal_chars, '_', name)
# 使用示例
if __name__ == "__main__":
source = r"C:\Music\Downloaded"
dest = r"C:\Music\Organized"
organize_music(source, dest)
批量重命名脚本
import os
import re
from pathlib import Path
def rename_music_files(directory, pattern="track_num - title"):
"""
批量重命名音乐文件
支持的模式: track_num, title, artist, album
"""
audio_extensions = {'.mp3', '.flac', '.wav', '.m4a', '.ogg'}
for file in os.listdir(directory):
file_path = os.path.join(directory, file)
if not os.path.isfile(file_path):
continue
ext = os.path.splitext(file)[1].lower()
if ext not in audio_extensions:
continue
# 这里简化处理,实际可以使用eyed3读取元数据
# 假设文件名格式为: "01 - Song Title.mp3"
parts = os.path.splitext(file)[0].split(" - ")
if len(parts) >= 2:
track_num = parts[0].zfill(2) # 补零
title = parts[1]
if pattern == "track_num - title":
new_name = f"{track_num} - {title}{ext}"
elif pattern == "title":
new_name = f"{title}{ext}"
else:
continue
new_path = os.path.join(directory, new_name)
os.rename(file_path, new_path)
print(f"重命名: {file} -> {new_name}")
# 使用示例
rename_music_files("C:/Music/Album", "track_num - title")
Shell脚本(Linux/Mac)
基础整理脚本
#!/bin/bash
# organize_music.sh
# 使用: ./organize_music.sh /source/dir /dest/dir
SOURCE_DIR="${1:-./music}"
DEST_DIR="${2:-./organized}"
# 支持的音频格式
EXTENSIONS="\.(mp3|flac|wav|m4a|ogg|wma)$"
find "$SOURCE_DIR" -type f | grep -iE "$EXTENSIONS" | while read -r file; do
filename=$(basename "$file")
# 使用exiftool获取元数据
if command -v exiftool &> /dev/null; then
artist=$(exiftool -Artist -b "$file" 2>/dev/null)
album=$(exiftool -Album -b "$file" 2>/dev/null)
fi
# 如果获取失败,尝试从文件名提取
if [ -z "$artist" ]; then
# 假设格式: "Artist - Album - Song.mp3"
artist=$(echo "$filename" | cut -d' -' -f1 | xargs)
album=$(echo "$filename" | cut -d' -' -f2 | xargs)
fi
# 清理文件名(替换非法字符)
artist=${artist//[<>:"\/\\|?*]/_}
album=${album//[<>:"\/\\|?*]/_}
# 设置默认值
artist=${artist:-"Unknown Artist"}
album=${album:-"Unknown Album"}
# 创建目标目录
dest_dir="$DEST_DIR/$artist/$album"
mkdir -p "$dest_dir"
# 复制文件
cp -n "$file" "$dest_dir/$filename"
echo "已整理: $filename -> $artist/$album/"
done
echo "整理完成!"
高级Shell脚本(带进度显示)
#!/bin/bash
# advanced_organize.sh
# 功能: 批量整理并备份音乐文件
clean_filename() {
echo "$1" | sed 's/[<>:"\/\\|?*]/_/g'
}
get_file_info() {
local file="$1"
local artist=""
local album=""
local title=""
# 尝试使用ffprobe获取元数据
if command -v ffprobe &> /dev/null; then
artist=$(ffprobe -v error -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
album=$(ffprobe -v error -show_entries format_tags=album -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
title=$(ffprobe -v error -show_entries format_tags=title -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)
fi
# 如果获取失败,尝试从文件名提取
if [ -z "$artist" ]; then
local filename=$(basename "$file")
# 格式: "Artist - Title.mp3"
if [[ "$filename" =~ ^(.+)\ -\ (.+)\..+$ ]]; then
artist="${BASH_REMATCH[1]}"
title="${BASH_REMATCH[2]}"
fi
fi
echo "$artist:${album:-'Unknown'}:${title:-$(basename "$file" .*) }"
}
# 主程序
main() {
local source_dir="${1:-./music}"
local dest_dir="${2:-./organized}"
local total_files=0
local processed=0
# 计数总文件数
total_files=$(find "$source_dir" -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.wav" -o -iname "*.m4a" -o -iname "*.ogg" \) | wc -l)
echo "找到 $total_files 个音乐文件,开始整理..."
find "$source_dir" -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.wav" -o -iname "*.m4a" -o -iname "*.ogg" \) | while read -r file; do
((processed++))
# 显示进度
printf "\r处理进度: %d/%d (%d%%)" $processed $total_files $((processed * 100 / total_files))
# 获取文件信息
IFS=':' read artist album title <<< "$(get_file_info "$file")"
# 清理并创建目录
artist=$(clean_filename "$artist")
album=$(clean_filename "$album")
dest_path="$dest_dir/$artist/$album"
mkdir -p "$dest_path"
# 复制文件(带校验)
cp -np "$file" "$dest_path/$title.${file##*.}" 2>/dev/null || {
echo -e "\n警告: 复制文件失败: $file"
}
done
echo -e "\n整理完成!"
}
# 运行主程序
main "$@"
PowerShell脚本(Windows)
# organize_music.ps1
# 使用: .\organize_music.ps1 -Source "C:\Music" -Destination "D:\Organized"
param(
[Parameter(Mandatory=$true)]
[string]$Source,
[Parameter(Mandatory=$false)]
[string]$Destination = ".\Organized",
[Parameter(Mandatory=$false)]
[switch]$CopyOnly = $false
)
# 加载Windows Media COM组件(需要管理员权限)
function Get-MusicMetadata {
param([string]$FilePath)
$shell = New-Object -ComObject Shell.Application
$folder = $shell.Namespace([System.IO.Path]::GetDirectoryName($FilePath))
$file = $folder.ParseName([System.IO.Path]::GetFileName($FilePath))
# 元数据列索引:20=艺术家, 14=专辑, 21=标题
$artist = $folder.GetDetailsOf($file, 20)
$album = $folder.GetDetailsOf($file, 14)
$title = $folder.GetDetailsOf($file, 21)
return @{
Artist = if ($artist) { $artist } else { "Unknown Artist" }
Album = if ($album) { $album } else { "Unknown Album" }
Title = if ($title) { $title } else { [System.IO.Path]::GetFileNameWithoutExtension($FilePath) }
}
}
# 清理文件名中的非法字符
function Clean-Name {
param([string]$Name)
$Name -replace '[<>:"/\\|?*]', '_'
}
# 主程序
Write-Host "开始整理音乐文件..." -ForegroundColor Green
$audioExtensions = @('.mp3', '.flac', '.wav', '.m4a', '.ogg', '.wma')
$files = Get-ChildItem -Path $Source -Recurse -File | Where-Object {
$_.Extension -in $audioExtensions
}
$total = $files.Count
$current = 0
foreach ($file in $files) {
$current++
$percent = [math]::Round(($current / $total) * 100, 1)
Write-Progress -Activity "整理音乐文件" -Status "处理: $($file.Name)" -PercentComplete $percent
try {
$metadata = Get-MusicMetadata -FilePath $file.FullName
$artist = Clean-Name -Name $metadata.Artist
$album = Clean-Name -Name $metadata.Album
$destFolder = Join-Path -Path $Destination -ChildPath "$artist\$album"
New-Item -ItemType Directory -Path $destFolder -Force | Out-Null
$destFile = Join-Path -Path $destFolder -ChildPath $file.Name
if ($CopyOnly) {
Copy-Item -Path $file.FullName -Destination $destFile -Force
} else {
Move-Item -Path $file.FullName -Destination $destFile -Force
}
Write-Host "处理完成: $($file.Name) -> $artist\$album" -ForegroundColor Green
}
catch {
Write-Warning "处理失败: $($file.Name) - $_"
}
}
Write-Progress -Activity "整理音乐文件" -Completed
Write-Host "整理完成!共处理 $total 个文件。" -ForegroundColor Green
使用建议
安装必要工具
# Python pip install eyed3 mutagen # Linux/Mac sudo apt install exiftool ffmpeg # Ubuntu/Debian brew install exiftool ffmpeg # Mac
先测试后正式运行
- 先在少量文件上测试
- 备份原始文件
- 使用
--dry-run参数预览操作
常见问题处理
- 乱码问题:使用
chardet库检测编码 - 重复文件:添加 MD5 校验
- 特殊字符:使用正则表达式清理
需要我详细解释某个部分或提供其他特定功能的脚本吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播