Извлечь оглавление файла epub

Извлечь оглавление файла epub

Недавно я наткнулся на команду, которая выводит оглавление файла pdf.

mutool show file.pdf outline

Я хотел бы использовать команду для epubформатирования с такой же простотой использования и хорошим результатом, как и приведенная выше команда для pdfформатирования.

Есть ли что-то подобное?

решение1

.epubфайлы — это .zipфайлы, содержащие XHTML и CSS, а также некоторые другие файлы (включая изображения, различные файлы метаданных и, возможно, XML-файл, называемый , toc.ncxсодержащий оглавление).

Следующий скрипт использует unzip -pдля извлечения toc.ncxв stdout, перенаправляет его черезxml2команду, а затем sedизвлечь только текст каждого заголовка главы.

В командной строке необходимо указать один или несколько аргументов имени файла.

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

Он выводит имя файла epub, за которым следует :, затем делает отступ для каждого заголовка главы на два пробела в следующих строках. Например:

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

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

Если файл epub не содержит toc.ncx, вы увидите следующий вывод для этой конкретной книги:

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

Первая строка ошибки — из unzip, вторая — из xml2. xml2также предупредит о других найденных ошибках — например, о неправильно отформатированном toc.ncxфайле.

Обратите внимание, что сообщения об ошибках выводятся на stderr, тогда как имя файла книги по-прежнему выводится на stdout.

xml2доступен в предварительно упакованном виде для Debian, Ubuntu и других производных от Debian, а также, вероятно, для большинства других дистрибутивов Linux.

Для таких простых задач (например, когда вы просто хотите преобразовать XML в строчно-ориентированный формат для использования с sed, awk, cut, grep, и т. д.) xml2проще и легче использовать, чем xmlstarlet.

Кстати, если вы хотите также напечатать название epub-файла, измените скрипт sedна:

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

или замените его скриптом awk:

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

решение2

Хотя ответ, предоставленный @cas, работает в некоторых случаях, он основан на предположении о версии epub 2.0 с документом NCX, названным toc.ncxна верхнем уровне zip-контейнера. Из 223 epub, которые у меня есть в одной папке, только 5 все еще соответствуют этому предположению — и они содержат его только для совместимости со старыми системами чтения. toc.ncxФайл не является обязательным — единственным обязательным файлом является META-INF/content.xml. Он будет содержать указатели на все остальные элементы epub. Это немного усложняет скриптование через bash, но возможно. Вот скрипт, который извлечет заголовок и автора из файла opf (на который указывает 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

Да, он анализирует opfдважды, чтобы обеспечить порядок результатов — это создает файл из трех столбцов, разделенных табуляцией (это табуляции в строках sed между двумя восклицательными знаками), подходящий для импорта электронных таблиц.

Пройти еще один шаг, чтобы найти файл ncx, немного сложнее, так как использование xml2 для генерации одной строки для каждого тега и атрибута здесь работает против нас: нам нужно значение атрибута, атрибут hrefкоторого media-typeравен application/x-dtbncx+xml. Мы можем немного схитрить и надеяться, что исходный элемент находится на одной строке, и использовать grep для извлечения только этого фрагмента, а затем обработать его с помощью xml2, чтобы получить значение href.

Поскольку это относительный URL, нам также нужно извлечь часть пути из записи opf. Собрав все вместе, мы получаем:

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

Это все еще делает предположения, самое сильное из которых заключается в том, что это файлы, совместимые с epub2, и, следовательно, содержащие файл ncx, где-то. Документы epub3 используют другой формат навигации на основе HTML. Несмотря на это, я получаю оглавления для всех 223 моих тестовых файлов (хотя у некоторых нет заголовков в ncx)

Связанный контент