Command Line – How to Extract TOC of EPUB File

command lineebooksepubfile format

Lately I hit the command that will print the TOC of a pdf file.

mutool show file.pdf outline

I'd like to use a command for the epub format with similar simplicity
of usage and nice result as the above for pdf format.

Is there something like that?

Best Answer

.epub files are .zip files containing XHTML and CSS and some other files (including images, various metadata files, and maybe an XML file called toc.ncx containing the table of contents).

The following script uses unzip -p to extract toc.ncx to stdout, pipe it through the xml2 command, then sed to extract just the text of each chapter heading.

It takes one or more filename arguments on the command line.

#! /bin/sh

# This script needs InfoZIP's unzip program
# and the xml2 tool from http://ofb.net/~egnor/xml2/
# and sed, of course.

for f in "$@" ; do
    echo "$f:"
    unzip -p "$f" toc.ncx | 
        xml2 | 
        sed -n -e 's:^/ncx/navMap/navPoint/navLabel/text=:  :p'
    echo
done

It outputs the epub's filename followed by a :, then indents each chapter title by two spaces on the following lines. For example:

book.epub:
  Chapter One
  Chapter Two
  Chapter Three
  Chapter Four
  Chapter Five

book2.epub:
  Chapter One
  Chapter Two
  Chapter Three
  Chapter Four
  Chapter Five

If an epub file doesn't contain a toc.ncx, you'll see output like this for that particular book:

book3.epub:
caution: filename not matched:  toc.ncx
error: Extra content at the end of the document

The first error line is from unzip, the second from xml2. xml2 will also warn about other errors it finds - e.g. an improperly formatted toc.ncx file.

Note that the error messages are on stderr, while the book's filename is still on stdout.

xml2 is available pre-packaged for Debian, Ubuntu and other debian-derivatives, and probably most other Linux distros too.

For simple tasks like this (i.e. where you just want to convert XML into a line-oriented format for use with sed, awk, cut, grep, etc), xml2 is simpler and easier to use than xmlstarlet.

BTW, if you want to print the epub's title as well, change the sed script to:

sed -n -e 's:^/ncx/navMap/navPoint/navLabel/text=:  :p
           s!^/ncx/docTitle/text=!  Title: !p'

or replace it with an awk script:

awk -F= '/(navLabel|docTitle)\/text/ {print $2}'
Related Question