Today I Learned : Making ebooks
As far as I’m concerned, I always liked bash scripts. Even if, I’m not good at it, especially in remembering syntax and conditions… (yeah, I always have to check on internet…).
Years ago, I have wrote an article about the making of ebooks in epub format. This year I wanted to write a script able to zip or unzip a folder into epub format.
Note: Obviously, an easier way to manipulate epubs would be using calibre, sigil or - if you’re a terminal aficionado - pandoc.
Fiat e-book et facta est e-book
As I wrote in this previous article, with the zip command in your bash/zsh terminal, you can create an epub file easily:
# Zip Options:
# -x exclude file
# -r recurse into directories
# -D do not add directory entries
# -9 compress better
# -X eXclude eXtra file attributes
# -0 store only
# create epub only with uncompressed mimetype:
zip -X0 <given ePub FilePath> mimetype
# add the other files to the epub:
zip -rDX9 <given ePub FilePath> * -x "*.DS_Store" -x mimetype
But to make this works properly you need to be sure that you have all the required files, the must important being the mimetype. With the following script, the e-book might not work if you’ve forgot the table of content or the container.xml
file, but I stated that I’ll check only the mimetype’s presence.
RED='\033[0;31m'
NC='\033[0m'
is_file(){
[[ -n "$1" ]] && [[ -f "$1" ]] && return 0 || return 1
}
local current_path
current_path=$(pwd)
echo -n "Name of your ebook: "
read -r book_name
echo -n "Path to the book folders and files: "
read -r book_path
if [ -n "${book_path}" ] && [ -d "$book_path" ];then
cd "$book_path" || return
clean_dot # remove macOS ._ files
if [ -n "${book_name}" ];then
local book=$book_name.epub
rm -f "$book"
else
echo -e "${RED}A book name is required.${NC}"
fi
mimetype_file=$(find . -name "mimetype")
if is_file "$mimetype_file";then
zip_epub "$book" "$mimetype_file"
mv "$book" "$current_path"/"$book"
cd "$current_path" || return
else
echo -e "${RED}A mimetype file is required.${NC}"
echo "Please check if your folder contains the mimetype file."
fi
else
echo -e "${RED}A path to the book files is required.${NC}"
echo "Please check the path given."
fi
To ease the creation, I ask the user the path of the book (read -r book_name
) to change directory (cd "$book_path"
), then I get the mimteype ($(find . -name "mimetype")
).
You can improve the script to check the other required files, of course.
Dissecting the epub
We used the zip command to create an epub e-book. Well, I guess we can use unzip command to extract the files from the epub file?!
As unzip
can’t extract directly from epub, I just needed to change epub extension to a zip one.
Basically, it’s cp file.epub file.zip
. I could have used mv
but I wanted to keep the epub file intact.
has_args(){
[[ "$1" -ne 0 ]] && return 0 || return 1
}
if has_args $#;then
if [[ $1 == *.epub ]]; then
local folder_name="${1%%.*}" # get name without extension
cp "$1" "$folder_name".zip # bash cannot unzip epub directly
unzip -oq "$folder_name".zip -d "./${folder_name}"
rm -f "$folder_name".zip
fi
else
echo -e "${RED}An error occurred.${NC}"
fi
UNZIP options:
-o : force rewriting
-q : don't display whole process
-d : unzip in given folder
That’s all folks!
You can find a whole script integrating these “tools” on github.