Extrair TOC do arquivo epub

2

Ultimamente eu acertei o comando que irá imprimir o TOC de um arquivo pdf .

mutool show file.pdf outline

Gostaria de usar um comando para o formato epub com simplicidade semelhante de uso e bom resultado como acima para o formato pdf .

Existe algo assim?

    
por xralf 19.05.2016 / 23:53

2 respostas

3

.epub arquivos são .zip arquivos contendo XHTML e CSS e alguns outros arquivos (incluindo imagens, vários arquivos de metadados e talvez um arquivo XML chamado toc.ncx contendo o índice).

O script a seguir usa unzip -p para extrair toc.ncx para stdout, canalizá-lo pelo comando xml2 e, em seguida, sed para extrair apenas o texto de cada título de capítulo.

Leva 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 : , em seguida, recua cada título do capítulo por dois espaços nas linhas a seguir. 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 essa para o livro em questão:

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

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

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

xml2 está disponível pré-empacotado para Debian, Ubuntu e outros derivados da Debian, e provavelmente a maioria das outras distribuições Linux também.

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

BTW, se você quiser imprimir o título do epub também, altere o script sed para:

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

ou substitua-o por um script awk :

awk -F= '/(navLabel|docTitle)\/text/ {print $2}'
    
por 20.05.2016 / 06:49
1

Embora a resposta fornecida pelo @cas funcione em alguns casos, ela se baseia na suposição de uma versão 2.0 do epub, com um documento NCX chamado toc.ncx no nível superior do contêiner zip. Dos 223 EPUBs que possuo em uma pasta, apenas 5 ainda atendem a essa suposição - e eles apenas a contêm para compatibilidade com sistemas de leitura mais antigos. O toc.ncx não é um arquivo obrigatório - o arquivo necessário é META-INF/content.xml . Isto irá 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 vai puxar título e autor do arquivo opf (apontado pelo 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, analisa o opf duas vezes, para garantir a ordem dos resultados - isso gera um arquivo de três colunas separado por tabulação (são guias 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, já que usar xml2 para gerar uma única linha para cada tag e atributo funciona aqui: precisamos do valor do atributo href who's media-type attribute é igual a application/x-dtbncx+xml . Podemos trapacear um pouco e esperar que o item original esteja todo em uma linha, e usar o grep para extrair apenas aquele fragmento, então processar isso com xml2 para obter o valor href.

Como esse é um URL relativo, também precisamos extrair a parte do caminho da entrada opf. Colocando tudo junto, 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, sendo a mais strong que são arquivos compatíveis com epub2 e, portanto, contêm um arquivo ncx em algum lugar. Os documentos do Epub3 usam um formato de navegação baseado em HTML diferente. Mesmo assim, eu obtenho TOCs para todos os 223 dos meus arquivos de teste (embora alguns não tenham títulos no ncx)

    
por 25.01.2017 / 22:13