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 epub
Format einen Befehl verwenden, der ähnlich einfach zu verwenden ist und gute Ergebnisse liefert wie der oben für pdf
das Format angegebene.
Gibt es so etwas?
Antwort1
.epub
Dateien sind .zip
Dateien, die XHTML und CSS sowie einige andere Dateien enthalten (einschließlich Bilder, verschiedene Metadatendateien und möglicherweise eine XML-Datei toc.ncx
mit dem Inhaltsverzeichnis).
Das folgende Skript unzip -p
extrahiert toc.ncx
es nach stdout, leitet es durch denxml2Befehl, um dann sed
nur 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
. xml2
warnt auch vor anderen gefundenen Fehlern – z. B. einer falsch formatierten toc.ncx
Datei.
Beachten Sie, dass die Fehlermeldungen auf stderr erscheinen, der Dateiname des Buchs jedoch weiterhin auf stdout steht.
xml2
ist 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) xml2
ist einfacher und leichter zu verwenden als xmlstarlet
.
Übrigens, wenn Sie auch den Titel des EPUBs drucken möchten, ändern Sie das sed
Skript wie folgt:
sed -n -e 's:^/ncx/navMap/navPoint/navLabel/text=: :p
s!^/ncx/docTitle/text=! Title: !p'
oder ersetzen Sie es durch ein awk
Skript:
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.ncx
auf 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.ncx
ist 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 opf
zweimal, 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 href
Attributs, dessen media-type
Attribut 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).