Últimamente presioné el comando que imprimirá el TOC de un pdf
archivo.
mutool show file.pdf outline
Me gustaría usar un comando para el epub
formato con una simplicidad de uso similar y un buen resultado como el anterior para pdf
el formato.
¿Hay algo como eso?
Respuesta1
.epub
Los archivos son .zip
archivos que contienen XHTML y CSS y algunos otros archivos (incluidas imágenes, varios archivos de metadatos y tal vez un archivo XML llamado toc.ncx
que contiene la tabla de contenido).
El siguiente script se utiliza unzip -p
para extraer toc.ncx
a la salida estándar y canalizarlo a través delxml2comando, luego sed
para 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
. xml2
También advertirá sobre otros errores que encuentre, por ejemplo, un toc.ncx
archivo 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.
xml2
está 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
, grep
etc.), xml2
es más simple y fácil de usar que xmlstarlet
.
Por cierto, si también desea imprimir el título del epub, cambie el sed
script a:
sed -n -e 's:^/ncx/navMap/navPoint/navLabel/text=: :p
s!^/ncx/docTitle/text=! Title: !p'
o reemplácelo con un awk
script:
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.ncx
en 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.ncx
un 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 opf
dos 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 href
atributo cuyo media-type
atributo 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).