1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env bash
# Ben Zanin, 2023-10-25
# If you have downloaded the Best of Bootie - Halloween 10 (2023) mashup
# from https://bootiemashup.com/mix-tapes/halloween-booootie-10-2023/
# only to discover that the MP3 files in the zip archive contain no tags
# at all, run this script to populate some meaningful values in there.
#
# You'll need a host system that has bash 4.x or greater. Linux and WSL
# or WSL2 under Windows should do; macOS has the unfortunate problem of
# offering only bash 3.x, you'll need to install something less moribund
# via 'brew install bash' or whatever mechanism you prefer.
#
# You'll also need the id3v2 utility installed, either via 'brew install
# id3v2' under macOS or 'apt-get install id3v2' under Debian/Ubuntu or
# however else you install software on your machine.
#
# This program looks for and honours two environment variables: 'DEBUG',
# which makes the output much more chatty on standard error, and
# USE_ID3V2_SLASH_SEPARATED_ARTISTS, which transforms the many artists
# in each metadata tag to be separated by slashes instead of their more
# human-friendly format listed on the Best of Bootie album page.
if ! command -v id3v2 > /dev/null 2>&1; then
>&2 printf 'could not find prerequisite tool: id3v2\n'
exit 1
fi
if [[ ! ${BASH_VERSINFO-UNSET} =~ ^[45] ]]; then
>&2 printf 'we need bash >= 4.2 to run but found %s\n' \
"${BASH_VERSINFO-no \$BASH_VERSINFO variable set}"
>&2 printf '(this program uses bash array features, see %s )\n' \
'https://mywiki.wooledge.org/BashFAQ/061'
exit 1
fi
declare -a fn_artists missing opts_id3v2
declare -i i tracktotal tracknum
declare fn artists title artist artist_tag_value
fn_artists=( \
'01 fnogg - Shake It Down In My Dragula.mp3' 'Rob Zombie vs. Taylor Swift vs. Disturbed'
'02 CastleR - There Will Be Life.mp3' 'Kim Petras vs. Backstreet Boys'
'03 Titus Jones - Gimme Sweet Halloween.mp3' 'Korn vs. ABBA vs. Beyoncé vs. Muse'
'04 reconthuse - Seven Nation Nightmare.mp3' 'Alice Cooper vs. White Stripes'
'05 IamJstncrdble - Haunted Thriller.mp3' 'Taylor Swift vs. Michael Jackson'
'06 iWillBattle - Vampire Hammer.mp3' 'Olivia Rodrigo vs. Ghost'
'07 iWillBattle - Mucky Mary [GaGa Muck].mp3' 'The Cramps vs. Lady Gaga'
"08 DSP - Somebody's Watching Girl.mp3" 'The Cure vs. Rockwell'
'09 MasDaMind - I’m Your Black Wolf.mp3' 'KC & the Sunshine Band vs. Zombie Hyperdrive'
'10 Lewis Wake - Scary Edge.mp3' 'Britney Spears vs. REZZ'
'11 Aggro1 - Zombie Rootkit.mp3' 'The Cranberries vs. Emurse'
'12 Voicedude - Werewolves On The Storm.mp3' 'Warren Zevon vs. The Doors + American Werewolf In London'
'13 Kill_mR_DJ - Spell Box.mp3' 'Screaming Jay Hawkins vs. Portishead vs. Creedence Clearwater Revival'
)
tracktotal=$((${#fn_artists[@]}/2))
for ((i=0; i<${#fn_artists[@]}; i+=2)); do
fn=${fn_artists[i]}
if [[ ! -f "$fn" ]]; then
missing+=($((1+(i/2))) "$fn")
fi
done
if ((${#missing[@]} > 0)); then
>&2 printf 'missing track %02d, filename: %s\n' "${missing[@]}"
exit 2
fi
for ((i=0; i<${#fn_artists[@]}; i+=2)); do
fn=${fn_artists[i+0]}
artists=${fn_artists[i+1]}
title=${fn#* - }
title=${title%.mp3}
artist=${fn%% - *}
artist=${artist:3}
tracknum=$((1+(i/2)))
if [[ $title == *Your\ Black\ Wolf* ]]; then
title=${title//’/\'}
fi
artist_tag_value="$artist: $artists"
if [[ ${USE_ID3V2_SLASH_SEPARATED_ARTISTS+SET} == 'SET' ]]; then
# not personally something I care about, but set and export this
# variable if you have strong opinions about separating multiple
# artists with slashes in the ID3v2 metadata
artist_tag_value=${artist_tag_value/: /\/}
artist_tag_value=${artist_tag_value// vs. /\/}
fi
opts_id3v2=( \
'--id3v2-only'
'--artist' "$artist_tag_value"
'--album' 'Best of Bootie - Halloween Bootie 10 (2023)'
'--song' "$title"
'--genre' 'bootie mashup'
'--year' '2023'
'--track' "$tracknum/$tracktotal"
'--comment' 'See album info at https //bootiemashup.com/mix-tapes/halloween-booootie-10-2023/'
# infuriatingly there seems to be no reasonable way to populate
# a comment tag with the id3v2 tag if that value contains a ":"
# character, so we use a stupid space instead. Harrumph.
#
# cf. https://www.jetmore.org/john/blog/2012/07/patch-allow-id3v21-to-include-colons-in-comment-fields/
# and http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=681847
)
if [[ ${DEBUG+SET} == 'SET' ]]; then
declare -p fn title artists artist tracknum tracktotal
printf 'id3v2:\n'
printf ' %-10s %s\n' \
"${opts_id3v2[0]}" '' "${opts_id3v2[@]:1}" "$fn" ''
fi
if ! id3v2 -R "$fn" | grep -q -E ': No ID3 tag$'; then
# don't mess around with files that already have metadata in them,
# no sense in complicating things. To start over just extract the
# MP3 files from the zip archive again.
>&2 printf 'file already has id3v2 metadata, skipping: %s\n' \
"$fn"
continue
fi
id3v2 "${opts_id3v2[@]}" "$fn"
done