37

使用 pdftk 合并多个 pdf 效果很好。但是,有什么简单的方法可以为每个合并的 pdf 添加书签吗?

我在 pdftk 文档上没有看到任何关于此的内容,所以我认为 pdftk 不可能。

我们合并的所有文件都将是 1 页,所以想知道之后是否有任何其他实用程序可以添加书签?

或者另一个基于 linux 的 pdf 实用程序,它允许在为每个单独的 pdf 指定书签的同时进行合并。

4

12 回答 12

43

您还可以使用 Ghostscript 合并多个 PDF。这条路线的最大优点是解决方案很容易编写脚本,并且不需要真正的编程工作:

gswin32c.exe ^
          -dBATCH -dNOPAUSE ^
          -sDEVICE=pdfwrite ^
          -sOutputFile=merged.pdf ^
          [...more Ghostscript options as needed...] ^
          input1.pdf input2.pdf input3.pdf [....]

使用 Ghostscript,您将能够传递pdfmark语句,该语句可以为进入生成的 PDF 的每个附加源文件添加目录和书签。例如:

gswin32c.exe ^
          -dBATCH -dNOPAUSE ^
          -sDEVICE=pdfwrite ^
          -sOutputFile=merged.pdf ^
          [...more Ghostscript options as needed...] ^
          file-with-pdfmarks-to-generate-a-ToC.ps ^
          -f input1.pdf input2.pdf input3.pdf [....]

或者

gswin32c.exe ^
          -dBATCH -dNOPAUSE ^
          -sDEVICE=pdfwrite ^
          -sOutputFile=merged.pdf ^
          [...more Ghostscript options as needed...] ^
          file-with-pdfmarks-to-generate-a-ToC.ps ^
          -f input1.pdf ^
             input2.pdf ^ 
             input3.pdf [....]

有关 pdfmark 主题的一些介绍,另请参阅 Thomas Merz 的PDFmark Primer


编辑:
我本来想给你举个例子file-with-pdfmarks-to-generate-a-ToC.ps,但不知何故忘记了。这里是:

[/Page 1 /View [/XYZ null null null] /Title (File 1) /OUT pdfmark
[/Page 2 /View [/XYZ null null null] /Title (File 2) /OUT pdfmark
[/Page 3 /View [/XYZ null null null] /Title (File 3) /OUT pdfmark
[/Page 4 /View [/XYZ null null null] /Title (File 4) /OUT pdfmark 

这将为前 4 个文件创建一个 ToC == 前 4 页(因为您保证您的成分文件对于合并的输出 PDF 各为 1 页)。

  1. 当您点击链接时,该[/XYZ null null null]部分可确保您的页面视口和缩放级别不会从当前更改。[/XYZ 222 111 2](如果你想要一个任意的例子,你可以说这样做。)
  2. /Title (some string you want)thingie 决定了 ToC 中的文本。

而且,您甚至可以直接将这些参数添加到 Ghostscript 命令行:

gswin32c.exe ^
       -o merged.pdf ^
       [...more Ghostscript options as needed...] ^
       -c "[/Page 1 /View [/XYZ null null null] /Title (File 1) /OUT pdfmark" ^
       -c "[/Page 2 /View [/XYZ null null null] /Title (File 2) /OUT pdfmark" ^
       -c "[/Page 3 /View [/XYZ null null null] /Title (File 3) /OUT pdfmark" ^
       -c "[/Page 4 /View [/XYZ null null null] /Title (File 4) /OUT pdfmark" ^
       -f input1.pdf ^
          input2.pdf ^ 
          input3.pdf ^ 
          input4.pdf [....]



'另一个编辑:

哦,顺便说一句:当您使用 Ghostscript 将两个 PDF 文件合并为一个时,Ghostscript确实会保留书签—— pdftk.exe 不会。让我们使用我第一次编辑的命令生成的那个(有效地连接同一文件的 2 个副本):

 gswin32c ^
    -sDEVICE=pdfwrite ^
    -o doublemerged.pdf ^
     merged.pdf ^
     merged.pdf

该文件doublemerged.pdf现在将有 2*4 = 8 个书签。

  • 符合预期:书签 1、2、3 和 4 链接到第 1、2、3 和 4 页。
  • 问题是,书签 5、6、7 和 8 也链接到第 1、2、3 和 4 页。

原因是,预先存在的书签确实通过绝对页码解决了它们的链接目标。为了解决这个问题(并且书签在合并文件中工作),必须生成书签,这些书签确实通过命名目的地指向链接目标(并确保这些在合并的文档中是唯一的)。

(这种方法也适用于 linux,只需使用 gs 而不是 gswin32c。)


附录

上面的命令行[...more Ghostscript options as needed...]用作更多选项的占位符。

如果您不使用其他选项,Ghostscript 将为各种参数应用其内置默认值。但是,这可能会给您带来您不喜欢的结果。由于 Ghostscript 会根据输入生成一个全新的 PDF,这意味着可能会更改一些原始对象。这适用于色彩空间和图像压缩级别。

如何应用使原始嵌入图像保持不变的参数可以在SuperUser 中看到:“使用 Ghostscript,但告诉它不要重新处理图像”

于 2010-06-24T09:57:26.977 回答
12

我知道已经提到了其他方法可以做到这一点,但是使用 pdftk,您可以获取合并的 pdf 并通过使用 pdftk 函数 dump_data 在 pdf 中创建现有信息的 .info 文件来为其添加书签。然后,您可以通过为每个书签添加以下四行来将书签信息添加到 .info 文件

BookmarkBegin
BookmarkTitle: name
BookmarkLevel: level
BookmarkPageNumber: page number

然后使用 update_info 调用将合并的 pdf 书签更新为您写入 .info 文件的书签。如果有人感兴趣,我已经编写了一些简单的函数,可以在 autohotkey 中为我执行此操作。请参阅http://www.autohotkey.com/board/topic/98985-scripts-to-merge-pdfs-and-add-bookmarks-with-pdftk/

于 2013-12-02T16:39:03.010 回答
5

也可以使用JPdfBookmarks添加或编辑 pdf 书签。它是一款出色的多操作系统自由软件工具,我已经使用了一段时间,效果非常好。它只处理书签,因此您需要另一个工具来合并或重新排序页面。除了 pdftk,我建议尝试PDF Split and Merge(好应用,但奇怪的 UI,根据我的经验搞乱了书签)、PDF-Shuffler(似乎工作正常,但有时在处理某些文件时会冻结)或PdfMod(最好的可能是因为它处理重新排列、合并和处理书签,尽管我无法弄清楚如何将 pdf 添加到特定页面中)。

很抱歉没有提供一些链接,作为一个新手,系统只允许我添加 2 个超链接。

于 2012-01-08T14:55:00.307 回答
5

请参阅https://stackoverflow.com/a/17781138/547578上的答案。我使用了一种叫做 Sejda 的东西。有用。它完美地结合了书签。谢谢@blablatros。

于 2013-07-22T09:02:38.707 回答
3

@pipitas 的好答案并没有解决完善的书签问题,并且在 unix 讨论中有相关问题https://unix.stackexchange.com/questions/17065/add-and-edit-bookmarks-to-pdf/ 31070,我建议的地方

如果您仍然坚持使用那些 unix 脚本,那么

  1. 提取从中转储的书签数据pdftk
  2. 编写一个额外的脚本将转储的书签数据转换为 pdfmarks 格式,gs接受 ghostscript 命令。
  3. 使用gs脚本将它们与 pdfmarks 合并在一起

该脚本已经存在,请参阅pdf-merge.pyMerge PDF's with PDFTK with Bookmarks?

于 2012-02-07T06:41:38.203 回答
3

也许以下内容会有所帮助。我想将位于一个目录中的所有 pdf (in_nn.pdf) 合并到一个 out.pdf,其中输入 pdf (in_nn) 的名称为 ToC。我编写了一个 python 脚本,它读取名称并提取页码并生成一个名为 pdfmarks 的文件。然后使用 gs 轻松合并文件。确切的命令由脚本输出,必须单独执行(可能由于页面大小调整或操作系统的原因进行了一些修改)。

这里是。Windows可能需要进行一些修改?(抱歉评论不是英文)。只需在要合并的pdf所在目录中执行python脚本即可。

#!/usr/bin/env python

import subprocess

# Dieses Skript dient dazu, eine Reihe von pdfs zu einem einzigen pdf zusammenzufassen und bookmarks fuer diese pdf-Datei zu erzeugen.
# Dafuer wird ein Datei pdfmark benoetigt, die mit diesem Skript erzeugt wird.
# Dazu einfach dieses Skript in dem Verzeichnis aufrufen, das genau alle zusammenzufassenden pdfs (*pdf, s.u.) enthaelt.
# Das zusammenfassende pdf wird dann mit diesem Befehl (in der bash) generiert:
# gs -dBATCH -dNOPAUSE -sPAPERSIZE=A4 -sDEVICE=pdfwrite -sOutputFile="all.pdf" $(ls *pdf ) pdfmarks
# Bereits Inhaltsverzeichnisse bleiben erhalten, die neuen kommen ans Ende des Inhaltsverzeichnisses.
#
# pdfmarks sieht dabei prinzipiell so aus:
#
# [/Title (Nr. 1) /Page 1 /OUT pdfmark
# [/Title (Nr. 2) /Page 5 /OUT pdfmark
# [/Title (Nr. 3) /Page 9 /OUT pdfmark
# usw.

p = subprocess.Popen('ls *pdf', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

pdfdateien = []
kombinationen = []

for line in p.stdout.readlines():
# p enthaelt alle pdf-Dateinamen
  pdfdateien.append(line)


for datei in pdfdateien:
  cmd = "pdfinfo %s" %datei 
  q=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  kombination = [datei]

for line in p.stdout.readlines():
# p enthaelt alle pdf-Dateinamen
  pdfdateien.append(line)


for datei in pdfdateien:
  cmd = "pdfinfo %s" %datei 
  q=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  kombination = [datei]


  for subline in q.stdout.readlines():
# q enthaelt die Zeilen von pdfinfo
    if "Pages" in subline:
      kombination.append(subline)

  kombinationen.append(kombination)


# Jetzt kombinationen in benoetigtes Format bringen:

kombinationen_bereinigt =  []
out_string1 = "[/Title ("
out_string2 = ") /Page "
out_string3 = " /OUT pdfmark\n"
seitenzahl = 1

for kombination in kombinationen:
  dateiname = kombination[0][0:len(kombination[0])-5]

#
# Hier noch dateiname evtl. verwursten
# z. B.
#  lesezeichen = dateiname[0:1]+" "+dateiname[6:8]+"/"+dateiname[1:5]
  lesezeichen = dateiname

  anz_seiten = kombination[1][16:len(kombination[1])-1]
  seitenzahl_str = str(seitenzahl)

  kombination_bereinigt = out_string1+lesezeichen+out_string2+seitenzahl_str+out_string3
  kombinationen_bereinigt.append(kombination_bereinigt)

  seitenzahl += int(anz_seiten)


# Ausgabe ins file
outfile = open("pdfmarks", "w")

for i in kombinationen_bereinigt:
  outfile.write(i)

outfile.close()

# Merge-Befehl absetzen

print "\nFor merging all pdfs execute this (or similar) command (in bash shell):"
print "gs -dBATCH -dNOPAUSE -sPAPERSIZE=A4 -sDEVICE=pdfwrite -sOutputFile=\"all.pdf\" $(ls *pdf ) pdfmarks\n"
于 2015-05-29T08:31:05.257 回答
3

最新版本pdftk(至少 v2.02)正确处理书签和链接:

pdftk file1.pdf file2.pdf cat output merged.pdf
于 2018-10-31T10:49:33.633 回答
1

不幸的是,没有简单的方法可以做到这一点。您可以使用直接构建 pdftk 的库,并编写使用 iText 或 iTextSharp 的 Java 或 .NET 程序来合并您的单页浏览器并创建书签。如果你想走 iText 路线,网上或 iText 书(由 iText 作者编写)中有很多示例。

...或者,让我知道什么不起作用,我可以提供帮助。

于 2010-06-29T10:44:38.900 回答
1

Sejda PDF(在其中一个答案中建议)也可作为在线服务提供:https ://www.sejda.com/merge-pdf 。

如果您不想安装任何其他软件并且更喜欢通过浏览器在线工作,这可能会派上用场。

合并步骤:

  1. 将所有 PDF 文件拖放到网页
  2. 默认情况下,所有现有书签都将保留,并且也可以在合并文档中使用。

  3. 或者,合并工具可以基于被合并的 PDF 文档构建目录

选择选项以根据文件名为合并的 PDF 文档生成目录

合并的 PDF 目录

合并 PDF 文件的在线服务可免费使用,每小时最多可处理 30 个文件和最多 50Mb/200 页的文件。

免责声明:我是一名在 Sejda 工作的开源开发人员。

于 2017-12-08T13:17:00.603 回答
0

以下是对 pdfmerger ( https://stackoverflow.com/a/30524828/3915004 ) 答案的评论。

感谢您的脚本 pdfmerger!我知道这个问题被标记为 linux,但是为了概括你的 Mac OS X 脚本,需要两件事:

  • 鬼脚本gs
  • 命令pdfinfo(例如包含在 中poppler

首先安装它们brew(谷歌它,它是通过一些 curl/ruby-magic 命令安装的 ^^ )然后简单地:

brew install ghostscript
brew install poppler

附加组件:阅读带有章节标题的文本文件:

扩展您的脚本。我将此工作流程主要用于可从编辑网站下载章节的书籍。可以轻松生成包含章节名称的文本文件。您的代码的以下附加组件额外读取一个文本文件“chapters.txt”,其中每个 pdf 包含一行以进行合并。(注意,我没有对与pdf数量对应的行数进行任何检查。)

只需通过替换以下行来扩展您的脚本:

p = subprocess.Popen('ls *pdf', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
c = subprocess.Popen('less chapters.txt', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

pdfdateien = []
kombinationen = []
chapternames = []

for line in c.stdout.readlines():
# c contains all chapter-titles
  chapternames.append(line)

for line in p.stdout.readlines():

for index, kombination in enumerate(kombinationen):
#  dateiname = kombination[0][0:len(kombination[0])-5]
#
# Hier noch dateiname evtl. verwursten
# z. B.
#  lesezeichen = dateiname[0:1]+" "+dateiname[6:8]+"/"+dateiname[1:5]
#  lesezeichen = dateiname
  lesezeichen=chapternames[index][:-1]

  anz_seiten = kombination[1][16:len(kombination[1])-1]
于 2015-12-14T21:57:56.267 回答
0

PdfMod。它具有图形界面,可让您手动添加书签。此外,如果您编辑带有书签的 PDF,它会自动更新它们以指向正确的页面。

于 2017-07-18T22:48:57.037 回答
0

缝合器

(安装pip install pystitcher

pystitcher 让您可以将 PDF 合并在一起,还可以通过在 markdown 文件中定义最终的 PDF 结构来轻松编辑书签。

因此,如果您的文件被调用1-5.pdf,您将创建一个降价文件(input.md):

# Part 1
[Chapter 1](1.pdf)
[Chapter 2](2.pdf)
[Chapter 3](3.pdf)
# Part 2
[Chapter 4](4.pdf)
[Chapter 5](5.pdf)

然后运行pystitcher input.md output.pdf,它将生成一个新的 PDF,其中添加了所有正确的书签。您还可以通过existing_bookmarks配置选项决定现有书签会发生什么。

于 2021-05-28T20:20:22.093 回答