因為客戶文件需要,得把一堆檔案輸出為pdf。懶人如我,當然要找一下是不是有好的方法可以達成這個需求。
第一個找到的是 pandoc ,這個工具好是好,但遇到 Ansible playbook ,pandoc 會以為檔案是設定檔,就沒辦法輸出。
第二個找到的是 enscript ,這工具就可以很輕易的將文字檔轉換為 postscript 檔案,同時還可以加上語法高亮效果,但可惜語法高亮效果不支援 Ansible playbook 。有了 postscript 檔案,接下來就可以用 ps2pdf 將 postscript 檔案轉換為 pdf。
# Ubuntu
sudo apt install ps2pdf enscript
enscript playbook.yml doc.ps
ps2pdf doc.ps doc.pdf
現在可以處理單一個檔案以後,接下來要想怎麼處理多個檔案,這裡透過 find, xargs 跟 enscript 的協作就可以做到
find . -name '*.yml' -print | xargs enscript --output=doc.ps
ps2pdf doc.ps doc.pdf
不免俗,還要加上頁首跟頁尾,頁尾也要加上頁次,這部份需要為 enscript 加上自訂的頁首跟調整頁尾的高度。
mkdir ~/.enscript
cp /usr/share/enscript/simple.hdr ~/.enscript/my.hdr
然後修改 ~/.enscript/my.hdr
% -- code follows this line --
%Format: fmodstr $D{%a %b %d %H:%M:%S %Y}
%Format: pagenumstr $V$%
%FooterHeight: 15
/do_header { % print default simple header
% Footer
gsave
d_footer_x d_footer_y HFpt_h 3 div add translate
HF setfont
user_footer_p {
d_footer_x d_footer_y moveto user_footer_left_str show
d_footer_w user_footer_center_str stringwidth pop sub 2 div
0 moveto user_footer_center_str show
d_footer_x d_footer_w add user_footer_right_str stringwidth pop sub
d_footer_y moveto user_footer_right_str show
} if
grestore
% Header
gsave
d_header_x d_header_y HFpt_h 3 div add translate
HF setfont
user_header_p {
5 0 moveto user_header_left_str show
d_header_w user_header_center_str stringwidth pop sub 2 div
0 moveto user_header_center_str show
d_header_w user_header_right_str stringwidth pop sub 5 sub
0 moveto user_header_right_str show
} {
5 0 moveto fname show
45 0 rmoveto fmodstr show
45 0 rmoveto pagenumstr show
} ifelse
grestore
} def
產出 postscript 的指令改為
find . -name '*.yml' -print | xargs enscript --fancy-header=my --header='$N||' --footer='|$%/%p|' --output=doc.ps
ps2pdf doc.ps doc.pdf
產出以後,會發現頁碼怪怪的,頁碼只有針對個別檔案,不是整份檔案,這下就傷腦筋了。經過Google 的幫忙,找到 pdftk 來幫忙。pdftk 是一個可以操作 pdf 的工具,可以作合併、加浮水印等等的功能。
最後的成果如下
DOC_PS=/tmp/doc.ps
RAW_DOC_PDF=/tmp/raw_doc.pdf
DOC_PDF=/tmp/doc.pdf
# 產出 postscript 檔案
find collections/ansible_collections/gov/twgcb/roles -name '*.yml' -print | xargs enscript \
--fancy-header=my \
--header='$N||' \
--footer='| |' \
--output=${DOC_PS}
# 前個步驟有產出 ps 檔案
if [[ -f ${DOC_PS} ]]; then
# 先轉為 pdf
ps2pdf ${DOC_PS} ${RAW_DOC_PDF}
# 取得頁數
number_of_pages=$(pdftk /tmp/doc.pdf dump_data | grep NumberOfPages | sed 's/NumberOfPages: //g')
# 印出
echo "number_of_pages=${number_of_pages}"
# 先產生一份空白的 pdf ,頁次重新編排,然後把這份 pdf 當作是前面產生的 pdf 的浮水印
# 這樣頁次就是對的了。
enscript -L1 --fancy-header=my --header='||' --footer '|$% / $=|' -o- < \
<(for i in $(seq 1 $number_of_pages); do echo; done) | \
ps2pdf - | \
pdftk ${RAW_DOC_PDF} multistamp - output ${DOC_PDF}
fi
參考資料
- Convert Text to PDF From the Command Line
- text processing – How to convert TXT to PDF? – Unix & Linux Stack Exchange
- enscript – add page numbers to pdf – Unix & Linux Stack Exchange
- bash – Printing footers using enscript – Ask Ubuntu
- Linux enscript — footer doesn’t work (final purpose is to add pager number at footer for PDF) – Stack Overflow
- Linux: Merge PDFs with page numbers | by Thomas Deniffel | Medium
- Add page numbers to a PDF Using seq (commandlinefu.com)
沒有留言:
張貼留言