.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}'