Created
October 19, 2021 22:17
-
-
Save YellowApple/7b9cc54cf6fbc20bf79cf2408b7f550d to your computer and use it in GitHub Desktop.
ID3-Tag-Inator: Automatically populates ID3 tags for all MP3 files in the Tri-State Area
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
SELF=$(basename $0) | |
usage () { | |
echo "usage: $SELF [-dfhv] [basedir]" | |
} | |
help () { | |
echo "\ | |
ID3-Tag-inator: Automatically populates ID3 tags for all MP3 files in the | |
Tri-State Area." | |
usage | |
echo ' | |
Options: | |
-d | |
Dry run (output ID3-editing commands instead of running them) | |
-f | |
Force updating ID3 tags even if they are already set | |
-h | |
This help screen | |
-v | |
Verbose output | |
Parameters: | |
basedir | |
A directory with subdirectories for each artist, each with | |
subdirectories for each album, each with MP3 files; defaults to the | |
current directory | |
Notes: | |
Artist, album, and title values are derived from the folder and file names | |
ID3-Tag-inator encounters, which no attempt to clean them up. It is up to | |
the user to rename the corresponding folders and files accordingly | |
beforehand. | |
Only MP3 files are supported, and their filenames must end in .mp3. | |
Copyright (C) 2021 Ryan S. Northrup ("RyNo") <[email protected]> | |
Permission to use, copy, modify, and distribute this software for any purpose | |
with or without fee is hereby granted, provided that the above copyright notice | |
and this permission notice appear in all copies. | |
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | |
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS | |
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | |
THIS SOFTWARE.' | |
exit 0 | |
} | |
badopt () { | |
echo "unknown option -- $1" | |
usage | |
exit 1 | |
} | |
dep_not_found () { | |
echo "$1 not found; exiting." | |
exit 1 | |
} | |
check_dep () { | |
which $1 >/dev/null 2>&1 || dep_not_found $1 | |
} | |
verbose () { | |
test $VERBOSE -gt 0 | |
} | |
dryrun () { | |
test $DRYRUN -gt 0 | |
} | |
force () { | |
test $FORCE -gt 0 | |
} | |
tag_is_unset () { | |
test -z "$(echo $1 | grep $2)" | |
} | |
current_tags () { | |
id3v2 -l "$1" | |
} | |
process_artist () { | |
ARTIST="$1" | |
verbose && echo "ARTIST: '$ARTIST'" | |
cd "$ARTIST" | |
pwd | |
for ALBUM in */; do | |
ALBUM=${ALBUM%*/} | |
process_album "$ALBUM" "$ARTIST" | |
done | |
cd .. | |
verbose && echo "================" | |
} | |
process_album () { | |
ALBUM="$1" | |
ARTIST="$2" | |
verbose && echo "ALBUM: '$ALBUM'" | |
cd "$ALBUM" | |
pwd | |
for TITLE in *.mp3; do | |
TITLE=${TITLE%*.mp3} | |
process_song "$TITLE" "$ALBUM" "$ARTIST" | |
done | |
cd .. | |
verbose && echo "----------------" | |
} | |
process_song () { | |
TITLE="$1" | |
ALBUM="$2" | |
ARTIST="$3" | |
CURRENT_TAGS=`current_tags "$TITLE.mp3"` | |
verbose && echo "PROCESS '$TITLE.mp3':" | |
COMMAND="id3v2" | |
if (force || tag_is_unset "$CURRENT_TAGS" TIT2); then | |
COMMAND="$COMMAND -t \"$TITLE\"" | |
verbose && echo " SET title (TIT2): \"$TITLE\"" | |
else | |
verbose && echo " SKIP title (TIT2); already set" | |
fi | |
if (force || tag_is_unset "$CURRENT_TAGS" TALB); then | |
COMMAND="$COMMAND -A \"$ALBUM\"" | |
verbose && echo " SET album (TALB): \"$ALBUM\"" | |
else | |
verbose && echo " SKIP album (TALB); already set" | |
fi | |
if (force || tag_is_unset "$CURRENT_TAGS" TPE1); then | |
COMMAND="$COMMAND -a \"$ARTIST\"" | |
verbose && echo " SET artist (TPE1): \"$ARTIST\"" | |
else | |
verbose && echo " SKIP artist (TPE1); already set" | |
fi | |
COMMAND="$COMMAND \"$TITLE.mp3\" >/dev/null 2>&1" | |
if dryrun; then | |
echo $COMMAND | |
else | |
eval "$COMMAND" | |
fi | |
} | |
VERBOSE=0 | |
DRYRUN=0 | |
FORCE=0 | |
while getopts ":vdfh" arg; do | |
case $arg in | |
v) | |
VERBOSE=1 | |
;; | |
d) | |
DRYRUN=1 | |
;; | |
f) | |
FORCE=1 | |
;; | |
h) | |
help | |
;; | |
*) | |
badopt $OPTARG | |
;; | |
esac | |
done | |
shift $((OPTIND-1)) | |
check_dep id3v2 | |
BASEPATH=${1:-.} | |
verbose && echo "Parameters:" | |
verbose && echo " BASEPATH: $BASEPATH" | |
verbose && echo " VERBOSE: $VERBOSE" | |
verbose && echo " DRYRUN: $DRYRUN" | |
verbose && echo " FORCE: $FORCE" | |
cd "$BASEPATH" | |
for ARTIST in */; do | |
pwd | |
ARTIST=${ARTIST%*/} | |
process_artist "$ARTIST" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment