#!/bin/sh usage() { cat >&2 <<'EOF' Usage: tagopus [OPTIONS] FILE... Options: -a ARTIST Set artist -b ALBUM Set album -y DATE Set date (year) -D Infer artist/album from directory structure (artist/album/NN title.opus) Explicit -a/-b flags override inferred values. Track number and title are inferred from each filename's leading numeric prefix. EOF exit 1 } artist= album= date= infer_dirs=0 while getopts 'a:b:y:D' opt; do case $opt in a) artist=$OPTARG ;; b) album=$OPTARG ;; y) date=$OPTARG ;; D) infer_dirs=1 ;; *) usage ;; esac done shift $((OPTIND - 1)) [ $# -eq 0 ] && usage # Validate fields that must come from flags and are always required err=0 [ -z "$date" ] && { printf 'Error: date is required (-y)\n' >&2; err=1; } # Without -D, artist/album must be supplied via flags if [ $infer_dirs -eq 0 ]; then [ -z "$artist" ] && { printf 'Error: artist is required (-a or -D)\n' >&2; err=1; } [ -z "$album" ] && { printf 'Error: album is required (-b or -D)\n' >&2; err=1; } fi [ $err -eq 1 ] && exit 1 numtracks=$# for f in "$@"; do base=$(basename "$f") name="${base%.opus}" # Extract leading numeric prefix as track number (variable width) tracknum=$(printf '%s' "$name" | sed -n 's/^\([0-9][0-9]*\).*/\1/p') if [ -z "$tracknum" ]; then printf 'Error: cannot parse track number from filename: %s\n' "$f" >&2 exit 1 fi # Title is everything after the numeric prefix and any whitespace title=$(printf '%s' "$name" | sed 's/^[0-9][0-9]*[[:space:]]*//') if [ -z "$title" ]; then printf 'Error: cannot parse title from filename: %s\n' "$f" >&2 exit 1 fi # Start with flag values; fill in from directory structure if -D and not already set file_artist=$artist file_album=$album if [ $infer_dirs -eq 1 ]; then album_dir=$(pwd) artist_dir=$(dirname "$album_dir") [ -z "$file_album" ] && file_album=$(basename "$album_dir") [ -z "$file_artist" ] && file_artist=$(basename "$artist_dir") fi # Final check — -D may have been given but paths might not resolve usefully err=0 [ -z "$file_artist" ] && { printf 'Error: could not determine artist for: %s\n' "$f" >&2; err=1; } [ -z "$file_album" ] && { printf 'Error: could not determine album for: %s\n' "$f" >&2; err=1; } [ $err -eq 1 ] && exit 1 opustags -i "$f" \ -s "artist=$file_artist" \ -s "album=$file_album" \ -s "date=$date" \ -s "tracknumber=$tracknum" \ -s "tracktotal=$numtracks" \ -s "title=$title" done