我正在搜索命令行工具以将书签添加到PDF文件。
我所拥有的是page number
和label
。很想创建一个名为label
的书签链接到页面page number
。
有没有人知道这样做的命令行工具(最好是OSX)?
我有大约4000页的PDF文件和大约150个书签,并希望自动化它。
我的计划是在r脚本中使用系统调用。
编辑
我用图表创建了大约4000个单独的PDF文件,我使用OSX系统命令/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py
将PDF连接在一起。以前我使用pdfjoin
包装的pdfjam
,但这太慢了。最后,这就是我获取PDF的方式,我现在用Adobe Acrobat Professional手工添加书签。
你也可以使用pdftk
。它也可用for OS X。
我现在没有详细介绍所有细节,因为它已经在其他地方完成了很长时间。简单地说:
pdftk my.pdf dump_data output -
pdftk my.pdf dump_data output bookmarks+otherdata.txt
pdftk my.pdf update_info bookmarks.txt output bookmarked.pdf
附加信息
这是我在上面的步骤4中检查后注意到的书签格式。
BookmarkBegin
BookmarkTitle: -- Your Title 1 --
BookmarkLevel: 1
BookmarkPageNumber: 1
BookmarkBegin
BookmarkTitle: -- Your Title 2 --
BookmarkLevel: 1
BookmarkPageNumber: 2
BookmarkBegin
BookmarkTitle: -- Your Title 3 --
...
...
and so on...
并在适当的地方更换以上..
好的,这是一个快速的方法,一次做三个工作:
它涉及使用LaTeX安装。
您从一个空的LaTeX模板开始,如下所示:
\documentclass[]{article}
\usepackage{pdfpages}
\usepackage{hyperref}
\hypersetup{breaklinks=true,
bookmarks=true,
pdfauthor={},
pdftitle={},
colorlinks=true,
citecolor=blue,
urlcolor=blue,
linkcolor=magenta,
pdfborder={0 0 0}}
\begin{document}
{
\hypersetup{linkcolor=black}
\setcounter{tocdepth}{3}
% Comment next line in or out if you want a ToC or not:
\tableofcontents
}
%% Here goes your additional code:
%% 1 line per included PDF!
\end{document}
现在就在此模板的最后一行之前,您要为每个要包含的外部PDF文件插入一行。
\includepdf[pages={<pagenumber>},addtotoc{<pagenumber>,<section>,<level>,\
<heading>,<label>}]{pdffilename.pdf}
\includepdf[addtotoc{<pagenumber>,<section>,<level>,\
<heading>,<label>}]]{pdffilename.pdf}
在这里,addtotoc
的所有以下五个参数都是必需的,按照给出的文件的顺序出现在书签和ToC中。请参阅下面的具体示例:
<pagenumber>
:要链接的插入文档的页面编号。 (在您的情况下始终为“1”,因为您只插入1页文档;您可以插入5页文档并链接到插入PDF的第3页)。<section>
:乳胶切片名称。可能是section
,subsection
,subsubsection
...在你的情况下“部分”。<level>
:LaTeX部分的水平。在你的情况下“1”。<heading>
:这是一个字符串。用于书签的文本<label>
:每个书签必须是唯一的。在内部使用PDF以在单击书签时跳转到正确的页面。为了快速测试,我使用Ghostscript生成了20页的1页PDF文档:
for i in {1..20}; do
gs -o p${i}.pdf -sDEVICE=pdfwrite \
-c "/Helvetica findfont 30 scalefont setfont \
100 600 moveto \
(Page ${i}) show \
showpage";
done
使用这些测试文件,我可以使插入模板的行看起来像这样:
\includepdf[addtotoc={1,section,1,Page 1 (First),p1}]{p1.pdf}
\includepdf[addtotoc={1,section,1,Page 2,p2}]{p2.pdf}
\includepdf[addtotoc={1,section,1,Page 3,p3}]{p3.pdf}
[...]
\includepdf[addtotoc={1,section,1,Page 11 (In the Middle),p11}]{p11.pdf}
[...]
\includepdf[addtotoc={1,section,1,Page 20 (Last),p20}]{p20.pdf}
使用插入的行保存模板,然后运行以下命令两次:
pdflatex template.tex
pdflatex template.tex
生成的文件将具有书签,在Preview.app中如下所示:
注意:LaTeX可通过两种方法用于OSX:
如果我有更多时间,我还会在命令行中添加一两个其他方法,以后或在接下来的几天内插入书签。
现在这个必须要做,因为我从来没有在SO,AFAICR上展示它。
但我想是因为你给出了背景“我正在合并1页PDF,而且它很慢;现在我也想添加书签......”,我可以用一种方法展示如何做到这一点。
提示:其他方法之一是使用适用于Mac OS X的pdftk
!
这是另一个答案。这个使用Ghostscript处理PDF-to-PDF和pdfmark
PostScript操作符来插入书签。
有关pdfmark主题的一些介绍,另请参阅:
此方法包括两个步骤:
pdfmark
命令,每行一个和要添加的书签。文本文件中的内容应如下所示:
[/Page 1 /View [/XYZ null null null] /Title (This is page 1) /OUT pdfmark
[/Page 2 /View [/XYZ null null null] /Title (Dunno which page this is....) /OUT pdfmark
[/Page 3 /View [/XYZ null null null] /Title (Some other name) /OUT pdfmark
[/Page 4 /View [/XYZ null null null] /Title (File 4) /OUT pdfmark
[/Page 5 /View [/XYZ null null null] /Title (File 5) /OUT pdfmark
[/Page 6 /View [/XYZ null null null] /Title (File 6) /OUT pdfmark
[/Page 7 /View [/XYZ null null null] /Title (File 7) /OUT pdfmark
% more lines for more pages to bookmark...
[/Page 13 /View [/XYZ null null null] /Title (File 13) /OUT pdfmark
[/Page 14 /View [/XYZ null null null] /Title (Bookmark for page 14) /OUT pdfmark
% more lines for more pages to bookmark...
将此文件命名为例如:addmybookmarks.txt
现在运行此命令:
gs -o bookmarked.pdf \
-sDEVICE=pdfwrite \
addmybookmarks.txt \
-f original.pdf
生成的PDF,bookmarked.pdf
现在包含书签。看这个截图:
这是将Bookmarks添加到目录的python方法。无需任何其他安装即可在MacOS上运行。
#!/usr/bin/python
from Foundation import NSURL, NSString
import Quartz as Quartz
import sys
# You will need to change these filepaths to a local test pdf and an output file.
infile = "/path/to/file.pdf"
outfile = "/path/to/output.pdf"
def getOutline(page, label):
# Create Destination
myPage = myPDF.pageAtIndex_(page)
pageSize = myPage.boundsForBox_(Quartz.kCGPDFMediaBox)
x = 0
y = Quartz.CGRectGetMaxY(pageSize)
pagePoint = Quartz.CGPointMake(x,y)
myDestination = Quartz.PDFDestination.alloc().initWithPage_atPoint_(myPage, pagePoint)
myLabel = NSString.stringWithString_(label)
myOutline = Quartz.PDFOutline.alloc().init()
myOutline.setLabel_(myLabel)
myOutline.setDestination_(myDestination)
return myOutline
pdfURL = NSURL.fileURLWithPath_(infile)
myPDF = Quartz.PDFDocument.alloc().initWithURL_(pdfURL)
if myPDF:
# Here's where you list your page index (starts at 0) and label.
outline1 = getOutline(0, 'Page 1')
outline2 = getOutline(1, 'Page 2')
outline3 = getOutline(2, 'Page 3')
# Create a root Outline and add each outline. (Needs a loop.)
rootOutline = Quartz.PDFOutline.alloc().init()
rootOutline.insertChild_atIndex_(outline1, 0)
rootOutline.insertChild_atIndex_(outline2, 1)
rootOutline.insertChild_atIndex_(outline3, 2)
myPDF.setOutlineRoot_(rootOutline)
myPDF.writeToFile_(outfile)