Extraer TOC del archivo epub

Extraer TOC del archivo epub

Últimamente presioné el comando que imprimirá el TOC de un pdfarchivo.

mutool show file.pdf outline

Me gustaría usar un comando para el epubformato con una simplicidad de uso similar y un buen resultado como el anterior para pdfel formato.

¿Hay algo como eso?

Respuesta1

.epubLos archivos son .ziparchivos que contienen XHTML y CSS y algunos otros archivos (incluidas imágenes, varios archivos de metadatos y tal vez un archivo XML llamado toc.ncxque contiene la tabla de contenido).

El siguiente script se utiliza unzip -ppara extraer toc.ncxa la salida estándar y canalizarlo a través delxml2comando, luego sedpara extraer solo el texto de cada título de capítulo.

Se necesitan uno o más argumentos de nombre de archivo en la línea de comando.

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

Genera el nombre del archivo epub seguido de :, luego sangra el título de cada capítulo con dos espacios en las siguientes líneas. Por ejemplo:

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

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

Si un archivo epub no contiene un archivo toc.ncx, verá un resultado como este para ese libro en particular:

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

La primera línea de error es de unzip, la segunda de xml2. xml2También advertirá sobre otros errores que encuentre, por ejemplo, un toc.ncxarchivo con formato incorrecto.

Tenga en cuenta que los mensajes de error están en stderr, mientras que el nombre de archivo del libro todavía está en stdout.

xml2está disponible preempaquetado para Debian, Ubuntu y otros derivados de Debian, y probablemente también para la mayoría de las otras distribuciones de Linux.

Para tareas simples como esta (es decir, cuando solo desea convertir XML a un formato orientado a líneas para usar con sed, awk, cut, grepetc.), xml2es más simple y fácil de usar que xmlstarlet.

Por cierto, si también desea imprimir el título del epub, cambie el sedscript a:

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

o reemplácelo con un awkscript:

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

Respuesta2

Si bien la respuesta proporcionada por @cas funciona en algunos casos, se basa en la suposición de un epub versión 2.0, con un documento NCX nombrado toc.ncxen el nivel superior del contenedor zip. De los 223 epubs que tengo en una carpeta, solo 5 todavía cumplen con esta suposición, y esos solo lo contienen por compatibilidad con sistemas de lectura más antiguos. No es toc.ncxun archivo obligatorio; el único archivo requerido es META-INF/content.xml. Este contendrá punteros a todos los demás elementos del epub. Esto hace que las secuencias de comandos mediante bash sean un poco más complejas, pero posibles. Aquí hay un script que extraerá el título y el autor del archivo opf (al que se señala a través de content.xml):

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

Sí, analiza opfdos veces para garantizar el orden de los resultados; esto genera un archivo de 3 columnas separados por tabulaciones (esas son pestañas en las líneas sed entre los dos flequillos), adecuado para la importación de hojas de cálculo.

Dar un paso más para encontrar el archivo ncx es un poco más complicado, ya que usar xml2 para generar una sola línea para cada etiqueta y atributo va en nuestra contra aquí: necesitamos el valor del hrefatributo cuyo media-typeatributo es igual a application/x-dtbncx+xml. Podemos hacer un poco de trampa y esperar que el elemento original esté todo en una línea, y usar grep para extraer solo ese fragmento, luego procesarlo con xml2 para obtener el valor href.

Como es una URL relativa, también necesitamos extraer la parte de la ruta de la entrada opf. Poniéndolo todo junto, nos da:

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

Esto todavía hace suposiciones, la más fuerte es que estos son archivos compatibles con epub2 y, por lo tanto, contienen un archivo ncx en alguna parte. Los documentos Epub3 utilizan un formato de navegación basado en HTML diferente. Aun así, obtengo TOC para los 223 archivos de prueba (aunque algunos carecen de títulos en el ncx).

información relacionada