Inhaltsverzeichnis einer EPUB-Datei extrahieren

Inhaltsverzeichnis einer EPUB-Datei extrahieren

Vor kurzem habe ich den Befehl gedrückt, der das Inhaltsverzeichnis einer Datei druckt pdf.

mutool show file.pdf outline

Ich möchte für das epubFormat einen Befehl verwenden, der ähnlich einfach zu verwenden ist und gute Ergebnisse liefert wie der oben für pdfdas Format angegebene.

Gibt es so etwas?

Antwort1

.epubDateien sind .zipDateien, die XHTML und CSS sowie einige andere Dateien enthalten (einschließlich Bilder, verschiedene Metadatendateien und möglicherweise eine XML-Datei toc.ncxmit dem Inhaltsverzeichnis).

Das folgende Skript unzip -pextrahiert toc.ncxes nach stdout, leitet es durch denxml2Befehl, um dann sednur den Text jeder Kapitelüberschrift zu extrahieren.

Es nimmt ein oder mehrere Dateinamenargumente in der Befehlszeile an.

#! /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

Es gibt den Dateinamen des Epubs gefolgt von einem aus :und rückt dann in den folgenden Zeilen jeden Kapiteltitel um zwei Leerzeichen ein. Beispiel:

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

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

Wenn eine EPUB-Datei kein enthält toc.ncx, wird für das jeweilige Buch eine Ausgabe wie diese angezeigt:

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

Die erste Fehlerzeile stammt von unzip, die zweite von xml2. xml2warnt auch vor anderen gefundenen Fehlern – z. B. einer falsch formatierten toc.ncxDatei.

Beachten Sie, dass die Fehlermeldungen auf stderr erscheinen, der Dateiname des Buchs jedoch weiterhin auf stdout steht.

xml2ist vorverpackt für Debian, Ubuntu und andere Debian-Derivate und wahrscheinlich auch für die meisten anderen Linux-Distributionen verfügbar.

Für einfache Aufgaben wie diese (d. h. wenn Sie XML lediglich in ein zeilenorientiertes Format zur Verwendung mit sed, awk, cut, grep, usw. konvertieren möchten) xml2ist einfacher und leichter zu verwenden als xmlstarlet.

Übrigens, wenn Sie auch den Titel des EPUBs drucken möchten, ändern Sie das sedSkript wie folgt:

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

oder ersetzen Sie es durch ein awkSkript:

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

Antwort2

Obwohl die von @cas bereitgestellte Antwort in einigen Fällen funktioniert, basiert sie auf der Annahme einer EPUB-Version 2.0 mit einem NCX-Dokument, das toc.ncxauf der obersten Ebene des Zip-Containers benannt ist. Von den 223 EPUBs, die ich in einem Ordner habe, erfüllen nur 5 diese Annahme – und diese enthalten es nur aus Kompatibilitätsgründen mit älteren Lesesystemen. Dies toc.ncxist keine erforderliche Datei – die einzige erforderliche Datei ist META-INF/content.xml. Diese enthält Zeiger auf alle anderen Elemente des EPUBs. Dies macht das Skripting über Bash etwas komplexer, aber möglich. Hier ist ein Skript, das Titel und Autor aus der OPF-Datei zieht (auf die über content.xml verwiesen wird):

#! /bin/sh

for f in "$@" ; do
    echo -n "$f""   "
    opf=$(unzip -p "$f" META-INF/container.xml | 
        xml2 | 
        sed -n -e 's:^/container/rootfiles/rootfile/@full-path=::p')
    unzip -p "$f" "$opf" |
        xml2 |
        sed -n -e 's!^/package/metadata/dc:title=!  !p' | tr  '
' ' '
    unzip -p "$f" "$opf" |
        xml2 |
        sed -n -e 's!^/package/metadata/dc:creator=!    !p' | tr  '
' ' '
    echo
done

Ja, es analysiert die Ergebnisse opfzweimal, um die Reihenfolge sicherzustellen. Dadurch wird eine durch Tabulatoren getrennte dreispaltige Datei generiert (das sind die Tabulatoren in den SED-Zeilen zwischen den beiden Ausrufezeichen), die für den Tabellenkalkulationsimport geeignet ist.

Einen Schritt weiter zu gehen, um die ncx-Datei zu finden, ist etwas schwieriger, da die Verwendung von xml2 zum Generieren einer einzelnen Zeile für jedes Tag und Attribut hier zu unseren Nachteilen führt: Wir benötigen den Wert des hrefAttributs, dessen media-typeAttribut gleich ist application/x-dtbncx+xml. Wir können ein bisschen schummeln und hoffen, dass das Originalelement vollständig in einer Zeile steht, und mit grep nur dieses Fragment extrahieren und es dann mit xml2 verarbeiten, um den href-Wert zu erhalten.

Da es sich um eine relative URL handelt, müssen wir auch den Pfadteil aus dem OPF-Eintrag extrahieren. Wenn wir alles zusammenfügen, erhalten wir:

#! /bin/sh

for f in "$@" ; do
    echo "$f""  "
    opf=$(unzip -p "$f" META-INF/container.xml | 
        xml2 | 
        sed -n -e 's:^/container/rootfiles/rootfile/@full-path=::p')
    ncx=$(unzip -p "$f" "$opf" |
        grep application/x-dtbncx+xml| 
        xml2 |
        sed -n -e 's!^/item/@href=!!p')
    opf_filename=${opf##*/}
    opf_path=${opf%$opf_filename}
    unzip -p "$f" ${opf_path}${ncx} |
        xml2 |
        sed -n -e 's:^/ncx/navMap/navPoint/navLabel/text=:  :p
                   s!^/ncx/docTitle/text=!Title: !p'
done

Dies erfordert immer noch Annahmen, wobei die stärkste Annahme ist, dass es sich um epub2-kompatible Dateien handelt und diese daher irgendwo eine ncx-Datei enthalten. Epub3-Dokumente verwenden ein anderes HTML-basiertes Navigationsformat. Trotzdem erhalte ich Inhaltsverzeichnisse für alle 223 meiner Testdateien (obwohl einigen die Titel in der ncx-Datei fehlen).

verwandte Informationen