用 pdftk-java 命令編輯 PDF 的四種方法
用這個(gè)方便的 Linux 命令合并 PDF、刪除頁(yè)面、分割 PDF 和填寫(xiě)表格。
技術(shù)白皮書(shū)、手稿和 RPG 手冊(cè),我每天都要處理大量的 PDF 文件。PDF 格式之所以受歡迎,是因?yàn)樗?jīng)過(guò)處理的 PostScript 代碼。PostScript 是現(xiàn)代打印機(jī)的原生語(yǔ)言,所以出版商經(jīng)常將一本書(shū)的數(shù)字版本發(fā)布為 PDF,因?yàn)樗麄円呀?jīng)投入了時(shí)間和精力來(lái)制作印刷用的文件。但是,PDF 并不是一種可編輯的格式,雖然可以進(jìn)行一些逆向處理,但它是數(shù)字?jǐn)?shù)據(jù)發(fā)送到打印機(jī)之前的最后一站。即便如此,有時(shí)你還是需要對(duì) PDF 進(jìn)行調(diào)整,而我最喜歡的工具之一就是 pdftk-java 命令。
在 Linux 上安裝 pdftk-java
顧名思義,pdftk-java
是用 Java 編寫(xiě)的,所以只要你安裝了 Java,它就能在所有主流的操作系統(tǒng)上工作。
Linux 和 macOS 用戶可以從 AdoptOpenJDK.net 安裝 Java。Windows 用戶可以安裝 Red Hat 的 OpenJDK 的 Windows版本。
要安裝 pdftk-java
:
1、從 Gitlab 倉(cāng)庫(kù)下載 pdftk-all.jar 程序,并將其保存到 ~/.local/bin/
或你 path 變量中的其他位置。
2、在你喜歡的文本編輯器中打開(kāi) ~/.bashrc
并添加這一行:
alias pdftk='java -jar $HOME/.local/bin/pdftk-all.jar'
3、加載你的新 Bash 設(shè)置:
$ source ~/.bashrc
命令語(yǔ)法
一個(gè)有效的 pdftk-java
命令的結(jié)構(gòu)遵循一個(gè)模式,但在模式中的內(nèi)容有很大的靈活性。語(yǔ)法有點(diǎn)不尋常,因?yàn)樗鼪](méi)有使用傳統(tǒng)風(fēng)格的 終端選項(xiàng),但經(jīng)過(guò)實(shí)踐,它并不難記。
pdftk
:調(diào)用該命令的別名- 輸入文件:你想修改的 PDF 文件
- 動(dòng)作:你想對(duì)輸入文件做什么
- 輸出:你想在哪里保存你修改過(guò)的 PDF 文件
最復(fù)雜的是動(dòng)作部分,所以我將從簡(jiǎn)單的任務(wù)開(kāi)始。
將兩個(gè) PDF 文件合并成一個(gè)
一本書(shū)的封面通常在一個(gè)單獨(dú)的應(yīng)用中創(chuàng)建,如 Inkscape 或 GIMP,而書(shū)的其他部分通常在 Scribus 等排版程序或 LibreOffice 等辦公套件中完成,這種情況并不罕見(jiàn)。你可以在你的排版應(yīng)用中把這兩者結(jié)合起來(lái)。像 Scribus 這樣的出版軟件可以很容易地引用一張圖片,這樣當(dāng)封面改變時(shí),它就會(huì)在版面中自動(dòng)更新。然而,也可以用 pdftk-java
將封面預(yù)置到 PDF 中:
$ pdftk cover.pdf body.pdf \
cat \
output book.pdf
在這個(gè)例子中,動(dòng)作是 cat
即 連接 的縮寫(xiě),和 Linux 的 cat 命令 一樣,它將一個(gè)或多個(gè) PDF 文件串聯(lián)成一個(gè)數(shù)據(jù)流,數(shù)據(jù)流被引導(dǎo)到“輸出”參數(shù)指定的任何文件中。
從一個(gè) PDF 中刪除頁(yè)面
你不能確切地從一個(gè) PDF 中刪除一頁(yè),但你可以創(chuàng)建一個(gè)新的 PDF,只包含你想保留的頁(yè)面。
$ pdftk book.pdf \
cat 1 3-end \
output shorter-book.pdf
在這個(gè)例子中,我的書(shū)的文件的第 1 頁(yè),以及從 3 到結(jié)尾的所有頁(yè)面,都被保存到一個(gè)新文件中。因此,我刪除的那一頁(yè)是第 2 頁(yè)。
將一個(gè) PDF 分割成不同的文件
將一個(gè) PDF 文件分割成許多不同的文件也使用 cat
動(dòng)作,它的原理與刪除頁(yè)面相似。你可以通過(guò)將你想要的頁(yè)面發(fā)送到一個(gè)新文件來(lái)分割一個(gè) PDF:
$ pdftk book.pdf \
cat 1-15 \
output part-1.pdf
$ pdftk book.pdf \
cat 16-42 \
output part-2.pdf
如果你需要將一個(gè) PDF 分割成單頁(yè)文件,有一個(gè)特殊的動(dòng)作,叫做 burst
:
$ pdftk book.pdf burst
$ ls
book.pdf pg_0001.pdf pg_0002.pdf
pg_0003.pdf pg_0004.pdf pg_0005.pdf
[...]
填寫(xiě)表格
很少有人能否認(rèn)多年來(lái) PDF 格式變得越來(lái)越臃腫,而你有時(shí)在 PDF 文件中發(fā)現(xiàn)的一個(gè)功能是可填寫(xiě)的表格。你會(huì)在美國(guó)稅務(wù)文件、RPG 角色表、線上學(xué)校作業(yè)本和其他旨在互動(dòng)的 PDF 文件中看到這種情況。雖然大多數(shù)現(xiàn)代的 PDF 瀏覽器,比如 GNOME 的 Evince 和 KDE 的 Okular,都可以填寫(xiě) PDF 表格,但你也可以在 pdftk-java
的幫助下填寫(xiě) PDF 表格。
首先,你必須使用 generate_fdf
動(dòng)作提取表單數(shù)據(jù)。這將提取表單元素的 ID,并將它們放入一個(gè)文本文件。
$ pdftk character-sheet.pdf \
generate_fdf \
output chsheet-form.txt
你的目標(biāo)文件(在這個(gè)例子中是 chsheet-form.txt
)包含 PDF 中的表格數(shù)據(jù),但只是文本部分。你可以在任何標(biāo)準(zhǔn)的文本編輯器中編輯它,如 Atom 或 Gedit。
在對(duì)生成 PDF 的組織的工作流程的有時(shí)令人欽佩和有時(shí)尷尬的一瞥中,你會(huì)發(fā)現(xiàn)一些表格有明確的標(biāo)簽,而其他表格有默認(rèn)的名字,如 “Checkbox_001” 和 “Textfield-021”,所以你可能要把你的文本文件和你的 PDF 對(duì)照一下,但如果你要寫(xiě)一個(gè)腳本來(lái)自動(dòng)填寫(xiě)表格,這可能是值得的。每個(gè)標(biāo)簽都被標(biāo)記為 /T
項(xiàng),在接下來(lái)的一行中,有空間(標(biāo)記為 /V
)提供給文本輸入。下面是一個(gè)片段,它的標(biāo)簽有上下文,并填入了一些數(shù)據(jù):
/T (CharacterName 2)
/V (Abaddon)
>>
<<
/T (SlotsTotal 24)
/V ()
>>
<<
/T (Hair)
/V (Brown)
>>
<<
/T (AC)
/V (15)
>>
<<
/T (Background)
/V ()
>>
<<
/T (DEXmod )
/V ()
當(dāng)你輸入了表單數(shù)據(jù),你就可以用 fill_form
動(dòng)作將你的文本輸入與 PDF 結(jié)構(gòu)結(jié)合起來(lái):
$ pdftk character-sheet.pdf \
fill_form chsheet-form.txt \
output completed.pdf
下面是一個(gè)結(jié)果示例。
A form filled by pdftk-java
PDF 修改變得簡(jiǎn)單
當(dāng)你處理大量的 PDF 文件或通過(guò) shell 腳本處理 PDF 文件時(shí),像 pdftk-java
這樣的工具是非常有價(jià)值的,因?yàn)樗鼓悴槐厥謩?dòng)做所有的事情。當(dāng)我從 Docbook 的輸出建立一個(gè) PDF 時(shí),它是一個(gè) Makefile,調(diào)用 pdftk-java
完成任何數(shù)量的任務(wù),所以我沒(méi)有機(jī)會(huì)忘記某個(gè)步驟或打錯(cuò)命令,也沒(méi)有必要把時(shí)間花在這上面。在你自己的工作流程中,還有很多其他的原因你可能會(huì)使用 pdftk-java
,它還可以做很多其他的事情,包括 shuffle
、rotate
、dump_data
、update_info
和 attach_files
等動(dòng)作。如果你發(fā)現(xiàn)自己經(jīng)常與 PDF 文件打交道,可以試試 pdftk-java
。