137 lines
2.8 KiB
Bash
137 lines
2.8 KiB
Bash
#!/usr/bin/env bash
|
|||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
RED=$'\e[31m'
|
||
|
|
GREEN=$'\e[32m'
|
||
|
|
RESET=$'\e[0m'
|
||
|
|
usage() {
|
||
|
|
cat <<EOF
|
||
|
|
Usage:
|
||
|
|
$(basename "$0") <library-root> <book-list> [--dry-run|--find-missing]
|
||
|
|
|
||
|
|
Arguments:
|
||
|
|
library-root Root containing author/*/book/
|
||
|
|
book-list Text file containing:
|
||
|
|
rank|title|author|year
|
||
|
|
|
||
|
|
Options:
|
||
|
|
--dry-run Show what would be tagged without writing tags
|
||
|
|
--find-missing List books from the ranking that were not found
|
||
|
|
EOF
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
[[ $# -ge 2 ]] || usage
|
||
|
|
|
||
|
|
ROOT="$1"
|
||
|
|
BOOKLIST="$2"
|
||
|
|
MODE="write"
|
||
|
|
|
||
|
|
case "${3:-}" in
|
||
|
|
--dry-run)
|
||
|
|
MODE="dryrun"
|
||
|
|
;;
|
||
|
|
--find-missing)
|
||
|
|
MODE="missing"
|
||
|
|
;;
|
||
|
|
"")
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
usage
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
[[ -d "$ROOT" ]] || {
|
||
|
|
echo "Library not found: $ROOT" >&2
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
[[ -f "$BOOKLIST" ]] || {
|
||
|
|
echo "Book list not found: $BOOKLIST" >&2
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
echo "Using MODE $MODE"
|
||
|
|
echo "Libary: $ROOT"
|
||
|
|
echo "File: $BOOKLIST"
|
||
|
|
|
||
|
|
normalize() {
|
||
|
|
echo "$1" |
|
||
|
|
tr '[:upper:]' '[:lower:]' |
|
||
|
|
sed -E "s/[^a-z0-9]+//g"
|
||
|
|
}
|
||
|
|
|
||
|
|
declare -A FOUND
|
||
|
|
|
||
|
|
while IFS='|' read -r RANK TITLE AUTHOR YEAR; do
|
||
|
|
|
||
|
|
# Skip blank lines and comments
|
||
|
|
[[ -z "$RANK" ]] && continue
|
||
|
|
[[ "$RANK" =~ ^# ]] && continue
|
||
|
|
|
||
|
|
NTITLE=$(normalize "$TITLE")
|
||
|
|
NAUTHOR=$(normalize "$AUTHOR")
|
||
|
|
|
||
|
|
MATCH=""
|
||
|
|
|
||
|
|
AUTHOR_PATH=$(find "$ROOT" -type d -iname "*$AUTHOR*" | head -n1)
|
||
|
|
|
||
|
|
[[ -z "$AUTHOR_PATH" ]] && continue
|
||
|
|
|
||
|
|
BOOK_PATH="$AUTHOR_PATH/book"
|
||
|
|
[[ -d "$BOOK_PATH" ]] || continue
|
||
|
|
|
||
|
|
while IFS= read -r FILE; do
|
||
|
|
FILE_NAME="${FILE##*/}"
|
||
|
|
FILE_BASE="${FILE_NAME%.*}"
|
||
|
|
|
||
|
|
echo "Checking: $FILE_BASE"
|
||
|
|
|
||
|
|
if [[ "$(normalize "$FILE_BASE")" == "$NTITLE" ]]; then
|
||
|
|
MATCH="$FILE"
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
done < <(find "$BOOK_PATH" -maxdepth 1 -type f)
|
||
|
|
if [[ -n "$MATCH" ]]; then
|
||
|
|
FOUND["$RANK"]=1
|
||
|
|
|
||
|
|
GROUP="Sci Fi Top 100 Books #$RANK"
|
||
|
|
|
||
|
|
case "$MODE" in
|
||
|
|
dryrun)
|
||
|
|
echo "Would tag:"
|
||
|
|
echo " File : $MATCH"
|
||
|
|
echo " Album: $GROUP"
|
||
|
|
echo " Year : $YEAR"
|
||
|
|
echo
|
||
|
|
;;
|
||
|
|
|
||
|
|
write)
|
||
|
|
echo "Tagging: $MATCH"
|
||
|
|
|
||
|
|
id3v2 \
|
||
|
|
--TALB "$GROUP" \
|
||
|
|
--TYER "$YEAR" \
|
||
|
|
"$MATCH"
|
||
|
|
;;
|
||
|
|
|
||
|
|
missing)
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
fi
|
||
|
|
|
||
|
|
done < "$BOOKLIST"
|
||
|
|
|
||
|
|
if [[ "$MODE" == "missing" ]]; then
|
||
|
|
while IFS='|' read -r RANK TITLE AUTHOR YEAR; do
|
||
|
|
[[ -z "$RANK" ]] && continue
|
||
|
|
[[ "$RANK" =~ ^# ]] && continue
|
||
|
|
|
||
|
|
if [[ -n "${FOUND[$RANK]:-}" ]]; then
|
||
|
|
printf "${GREEN}FOUND${RESET} #%3d | %s | %s | %s\n" \
|
||
|
|
"$RANK" "$TITLE" "$AUTHOR" "$YEAR"
|
||
|
|
else
|
||
|
|
printf "${RED}MISSING${RESET} #%3d | %s | %s | %s\n" \
|
||
|
|
"$RANK" "$TITLE" "$AUTHOR" "$YEAR"
|
||
|
|
fi
|
||
|
|
done < "$BOOKLIST"
|
||
|
|
fi
|