最近我點擊了列印文件目錄的指令pdf
。
mutool show file.pdf outline
我想使用一個epub
與上述格式類似的簡單用法和良好結果的命令pdf
。
有這樣的事嗎?
答案1
.epub
文件是.zip
包含 XHTML 和 CSS 以及其他一些文件(包括圖像、各種元資料文件,可能還有一個稱為toc.ncx
包含目錄的 XML 文件)的文件。
以下腳本用於unzip -p
提取toc.ncx
到標準輸出,透過管道將其傳輸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 個仍然滿足這一假設 - 並且這些 epub 包含它只是為了與舊的閱讀器系統相容。這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
兩次,以確保結果的順序 - 這會產生一個製表符分隔的 3 列檔案(這些是兩個瀏海之間的 sed 行中的製表符),適合電子表格匯入。
再一步找 ncx 檔案有點棘手,因為使用 xml2 為每個標籤和屬性產生一行對我們不利:我們需要屬性等於 的屬性href
的值。我們可以作一點欺騙,希望原始項目全部在一行上,然後使用 grep 提取該片段,然後使用 xml2 處理它以獲得 href 值。media-type
application/x-dtbncx+xml
由於這是一個相對 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 中缺少標題)