Shell脚本处理音频元数据需求咨询:读取、码率校验、重命名与移动
Hey Sebastian, great question! Since you're new to shell scripting, let's break this down into manageable parts—starting with the trickiest bit: reading metadata, then moving through each feature you need.
First: The Right Tool for Metadata Reading
Forget trying to use separate tools for each format (like id3v2 for MP3, metaflac for FLAC)—ffprobe (part of the FFmpeg suite) is your one-stop shop. It supports WAV, FLAC, MP3, AIFF, and almost every other audio format, so you won't have to juggle multiple commands.
Step 1: Install FFmpeg
First, get ffprobe on your system:
- On Debian/Ubuntu:
sudo apt install ffmpeg - On macOS (with Homebrew):
brew install ffmpeg - On Windows: Grab a pre-built binary from FFmpeg's official site (note: shell scripting on Windows is trickier—we’ll cover alternatives later)
Step-by-Step Shell Script Implementation
Here's a working skeleton script with comments to explain each part. You can tweak variables like BITRATE_THRESHOLD and TARGET_DIR to fit your needs:
#!/bin/bash # Configure these variables first! BITRATE_THRESHOLD=192000 # 192 kbps (value is in bits per second) TARGET_DIR="/path/to/your/target/folder" # Make sure target directory exists (create if not) mkdir -p "$TARGET_DIR" # Loop through all supported audio files in the current directory for audio_file in *.{wav,flac,mp3,aiff}; do # Skip if the file doesn't exist (avoids errors if no files of a type are present) [[ -f "$audio_file" ]] || continue echo "Processing $audio_file..." # Extract metadata using ffprobe # Pulls artist, title, release date, and bitrate in one go read -r artist title year bitrate <<< "$(ffprobe -v error \ -show_entries format_tags=artist,title,date \ -show_entries format=bit_rate \ -of default=noprint_wrappers=1:nokey=1 "$audio_file")" # Handle missing metadata (replace with default values if needed) artist=${artist:-"Unknown_Artist"} title=${title:-"Unknown_Title"} year=${year:-"Unknown_Year"} bitrate=${bitrate:-0} # Check bitrate threshold if (( bitrate < BITRATE_THRESHOLD )); then echo "ERROR: $audio_file has bitrate $((bitrate/1000)) kbps, below threshold of $((BITRATE_THRESHOLD/1000)) kbps" continue # Skip to next file fi # Get file extension (lowercase for consistency) ext=$(echo "$audio_file" | awk -F . '{print tolower($NF)}') # Create new filename (replace spaces with underscores to avoid shell parsing issues) new_filename="${artist// /_}-${title// /_}-${year}.${ext}" # Rename and move the file mv "$audio_file" "$TARGET_DIR/$new_filename" echo "Moved and renamed to $TARGET_DIR/$new_filename" done echo "Processing complete!"
Key Notes for the Script:
- Metadata Safety: The
readcommand capturesffprobeoutput into variables. We use${var:-default}to handle missing metadata so the script doesn’t crash. - Bitrate Logic:
ffprobereturns bitrate in bits per second, so we divide by 1000 to get user-friendly kbps values. - Filename Cleanup: Replacing spaces with underscores (
${var// /_}) prevents shell errors—you can remove this if you prefer to keep spaces (just always wrap variables in quotes!).
Alternative Solutions (If Shell Scripting Feels Too Clunky)
If you find shell scripting limiting (especially with edge cases like weird metadata formats), here are two great alternatives:
1. Python with Mutagen
Mutagen is a powerful Python library for reading audio metadata. It’s more flexible than shell scripts and easier to handle complex logic. Here’s a quick example:
import os from mutagen import File BITRATE_THRESHOLD = 192000 # 192 kbps TARGET_DIR = "/path/to/your/target/folder" os.makedirs(TARGET_DIR, exist_ok=True) for filename in os.listdir("."): ext = filename.lower().split(".")[-1] if ext not in ["wav", "flac", "mp3", "aiff"]: continue audio = File(filename, easy=True) if not audio: print(f"ERROR: Could not read metadata for {filename}") continue # Extract metadata (with defaults) artist = audio.get("artist", ["Unknown_Artist"])[0] title = audio.get("title", ["Unknown_Title"])[0] year = audio.get("date", ["Unknown_Year"])[0].split("-")[0] # Grab just the year part bitrate = audio.info.bitrate if hasattr(audio.info, "bitrate") else 0 if bitrate < BITRATE_THRESHOLD: print(f"ERROR: {filename} has bitrate {bitrate//1000} kbps, below threshold") continue new_filename = f"{artist.replace(' ', '_')}-{title.replace(' ', '_')}-{year}.{ext}" os.rename(filename, os.path.join(TARGET_DIR, new_filename)) print(f"Moved to {os.path.join(TARGET_DIR, new_filename)}")
2. GUI/Automated Tools
If you don’t want to code at all, tools like MusicBrainz Picard can batch rename and organize audio files, check bitrates, and fix metadata. It’s great for non-technical users, but less flexible than scripts for custom workflows.
内容的提问来源于stack exchange,提问作者Sebastian




