Skip to content

Instantly share code, notes, and snippets.

@markfaine
Created January 3, 2021 21:26
Show Gist options
  • Save markfaine/7b3c4752ba3b9e04120ab4cbca7b3b16 to your computer and use it in GitHub Desktop.
Save markfaine/7b3c4752ba3b9e04120ab4cbca7b3b16 to your computer and use it in GitHub Desktop.
Calibre on Linux doesn't write out the file names properly because they are paranoid that you might try to move it to an operating system that doesn't support those characters.
#!/bin/bash
#shellcheck shell=bash
# Requires unzip and xmlstarlet
# Assumes that you are extracting metadata as well, though you could extract
# the opf from the epub at run time but I don't know how to do this for other
# formats
# I also only get the first author because I didn't want to deal with adding
# '&' or ',' or ', and' for each author, and determing when each is appropriate
# Assumes you want a format of 'Author Name/Book Name/Book Name.extension'
# But it wouldn't take much to change it to whatever format you want
basedir="$1"
basedir="$(readlink -f "$basedir")"
if [[ ! -d "$basedir" ]]; then
echo "$basedir was not found or is inaccessible!"
exit 1
fi
mapfile -t books < <(find "$basedir" -type f -name '*.opf')
for book in "${books[@]}"; do
dname="$(dirname "$book")"
title="$(xmlstarlet sel -N opf="http://www.idpf.org/2007/opf" \
-N dc="http://purl.org/dc/elements/1.1/" -t -m \
'/opf:package/opf:metadata/dc:title' -v . -n "$book")"
mapfile -t authors < <(xmlstarlet sel -N \
opf="http://www.idpf.org/2007/opf" \
-N dc="http://purl.org/dc/elements/1.1/" -t -m \
'/opf:package/opf:metadata/dc:creator' -v . -n "$book")
author="${authors[0]}"
# Fix the filenames of the exported files
mapfile -t book_files < <(find "$dname" -type f)
for book_file in "${book_files[@]}"; do
bname="$(basename "$book_file")"
dname="$(dirname "$book_file")"
fname="${bname%%\.*}"
extension="${book_file##*\.}"
if [[ "$fname" != "$title" ]]; then
mv "${book_file}" "${dname}/${title}.${extension}"
fi
done
# Fix the title directory if it's different
title_dir="$(dirname "$book")"
title_dir_dname="$(dirname "$title_dir")"
title_dir_name="$(basename "$title_dir" )"
if [[ "$title_dir_name" != "$title" ]]; then
mv "$title_dir" "${title_dir_dname}/${title}"
fi
# Fix the author directory if it's different
author_dir="$(dirname "$title_dir")"
author_dir_dname="$(dirname "$author_dir")"
author_dir_name="$(basename "$author_dir" )"
if [[ "$author_dir_name" != "$author" ]]; then
mv "$author_dir" "${author_dir_dname}/${author}"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment