Extraia o TOC do arquivo epub

Extraia o TOC do arquivo epub

Ultimamente apertei o comando que irá imprimir o TOC de um pdfarquivo.

mutool show file.pdf outline

Eu gostaria de usar um comando para o epubformato com simplicidade de uso semelhante e bons resultados como o pdfformato acima.

Existe algo assim?

Responder1

.epubarquivos são .ziparquivos contendo XHTML e CSS e alguns outros arquivos (incluindo imagens, vários arquivos de metadados e talvez um arquivo XML chamado toc.ncxcontendo o índice analítico).

O script a seguir usa unzip -ppara extrair toc.ncxpara stdout, canalizá-lo através doxml2comando e, em seguida, sedextrair apenas o texto de cada título de capítulo.

São necessários um ou mais argumentos de nome de arquivo na linha 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

Ele exibe o nome do arquivo do epub seguido por um :e, em seguida, recua o título de cada capítulo com dois espaços nas linhas seguintes. Por exemplo:

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

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

Se um arquivo epub não contiver um toc.ncx, você verá uma saída como esta para esse livro específico:

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

A primeira linha de erro é from unzip, a segunda from xml2. xml2também avisará sobre outros erros encontrados - por exemplo, um toc.ncxarquivo formatado incorretamente.

Observe que as mensagens de erro estão em stderr, enquanto o nome do arquivo do livro ainda está em stdout.

xml2está disponível pré-empacotado para Debian, Ubuntu e outros derivados do Debian, e provavelmente para a maioria das outras distros Linux também.

Para tarefas simples como esta (ou seja, onde você deseja apenas converter XML em um formato orientado a linhas para usar com sed, awk, cut, grep, etc), xml2é mais simples e fácil de usar do que xmlstarlet.

Aliás, se você quiser imprimir também o título do epub, altere o sedscript para:

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

ou substitua-o por um awkscript:

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

Responder2

Embora a resposta fornecida por @cas funcione em alguns casos, ela é baseada na suposição de uma versão 2.0 do epub, com um documento NCX nomeado toc.ncxno nível superior do contêiner zip. Dos 223 epubs que tenho em uma pasta, apenas 5 ainda atendem a essa suposição - e esses contêm apenas para compatibilidade com sistemas de leitura mais antigos. O toc.ncxarquivo não é obrigatório - o arquivo obrigatório é META-INF/content.xml. Isto conterá ponteiros para todos os outros elementos do epub. Isso torna o script via bash um pouco mais complexo, mas possível. Aqui está um script que extrairá o título e o autor do arquivo opf (apontado por meio do 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

Sim, ele analisa opfduas vezes, para garantir a ordem dos resultados - isso gera um arquivo de 3 colunas separado por tabulações (são tabulações nas linhas sed entre as duas franjas), adequado para importação de planilhas.

Dar mais um passo para encontrar o arquivo ncx é um pouco mais complicado, pois usar xml2 para gerar uma única linha para cada tag e atributo funciona contra nós aqui: precisamos do valor do hrefatributo cujo media-typeatributo é igual a application/x-dtbncx+xml. Podemos trapacear um pouco e esperar que o item original esteja todo em uma linha, e usar grep para extrair apenas esse fragmento e, em seguida, processá-lo com xml2 para obter o valor href.

Como esse é um URL relativo, também precisamos extrair a parte do caminho da entrada opf. Juntando tudo, nos dá:

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

Isso ainda faz suposições, a mais forte é que esses arquivos são compatíveis com epub2 e, portanto, contêm um arquivo ncx em algum lugar. Os documentos Epub3 usam um formato de navegação baseado em HTML diferente. Mesmo assim, recebo TOCs para todos os 223 arquivos de teste (embora alguns não tenham títulos no ncx)

informação relacionada