Ultimamente apertei o comando que irá imprimir o TOC de um pdf
arquivo.
mutool show file.pdf outline
Eu gostaria de usar um comando para o epub
formato com simplicidade de uso semelhante e bons resultados como o pdf
formato acima.
Existe algo assim?
Responder1
.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 analítico).
O script a seguir usa unzip -p
para extrair toc.ncx
para stdout, canalizá-lo através doxml2comando e, em seguida, sed
extrair 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
. xml2
também avisará sobre outros erros encontrados - por exemplo, um toc.ncx
arquivo formatado incorretamente.
Observe que as mensagens de erro estão em stderr, enquanto o nome do arquivo do livro ainda está em stdout.
xml2
está 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 sed
script para:
sed -n -e 's:^/ncx/navMap/navPoint/navLabel/text=: :p
s!^/ncx/docTitle/text=! Title: !p'
ou substitua-o por um awk
script:
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.ncx
no 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.ncx
arquivo 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 opf
duas 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 href
atributo cujo media-type
atributo é 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)