Объединить PDF с PDFTK с закладками?

Использование pdftk для объединения нескольких PDF-файлов работает хорошо. Тем не менее, любой простой способ сделать закладку для каждого объединенного PDF?

Я не вижу ничего в документации по pdftk по этому поводу, поэтому я не думаю, что это возможно с pdftk.

Все наши файлы будут объединены в одну страницу, так что интересно, есть ли какая-нибудь другая утилита, которая впоследствии может добавить в закладки?

Или другую pdf-утилиту на основе linux, которая позволит объединяться при указании закладки для каждого отдельного pdf.

12 ответов

Вы также можете объединить несколько PDF-файлов с Ghostscript. Большим преимуществом этого пути является то, что решение легко поддается написанию сценариев и не требует реального программирования:

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, см. Также учебник PDFmark Томаса Мерца.


Редактировать:
Я хотел дать вам пример для 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 

Это создаст ToC для первых 4 файлов == первых 4 страниц (так как вы гарантируете, что ваши файлы ингредиентов по одной странице для вашего объединенного выходного PDF).

  1. [/XYZ null null null] part гарантирует, что область просмотра и уровень масштабирования вашей страницы не изменятся с текущего при переходе по ссылке. (Ты мог бы сказать [/XYZ 222 111 2] сделать это, если вы хотите произвольный пример.)
  2. /Title (some string you want) Вещи определяет, что текст в 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-файлов в один - 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, но скажите, чтобы он не обрабатывал изображения".

Я знаю, что другие способы сделать это уже упоминались, но с помощью pdftk вы можете взять объединенный файл PDF и добавить в него закладки, используя функцию dump_data pdftk, чтобы создать файл.info с существующей информацией в файле PDF. Затем вы можете добавить информацию о закладке в файл.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/

Смотрите этот ответ на /questions/3070026/sozdajte-odin-pdf-fajl-dokumentatsii-python/3070039#3070039. Я использовал что-то под названием Сейда. Оно работает. Он отлично сочетает в себе закладки. Спасибо @blablatros.

Чтобы добавить или отредактировать PDF-закладки, вы можете использовать JPdfBookmarks. Это отличный инструмент для работы с несколькими ОС, который я использую уже некоторое время, и который дает отличные результаты. Он работает только с закладками, поэтому вам понадобится другой инструмент для объединения или изменения порядка страниц. В дополнение к pdftk я предлагаю попробовать PDF Split and Merge (хорошее приложение, но странный интерфейс, портит закладки из моего опыта), PDF-Shuffler (кажется, работает нормально, но иногда зависает при работе с некоторыми файлами), или PdfMod (лучше всего, поскольку это касается перестановки, слияния и работы с закладками, хотя я не смог понять, как добавить PDF-файлы на определенную страницу).

Извините, что не предоставил некоторые ссылки, поскольку новичок система позволяет мне добавить только 2 гиперссылки.

Последняя версия pdftk (по крайней мере v2.02) правильно обрабатывает закладки и ссылки:

pdftk file1.pdf file2.pdf cat output merged.pdf

Хороший ответ @pipitas не решает проблемы с закладками, а также есть связанные вопросы в обсуждении Unix https://unix.stackexchange.com/questions/17065/add-and-edit-bookmarks-to-pdf/31070, где я предлагаю

Если вы все еще придерживаетесь этих сценариев Unix, то

  1. извлекать данные закладок, выгруженных из pdftk
  2. написать один дополнительный скрипт для преобразования сброшенных данных закладок в формат pdfmarks, используя команду ghostscript gs принято
  3. использование gs скрипт для объединения их вместе с pdfmarks

Сценарий уже существует, смотрите pdf-merge.py от слияния PDF с PDFTK с закладками?

Может быть, следующее полезно. Я хотел объединить все PDF-файлы (in_nn.pdf), расположенные в одном каталоге, в один out.pdf, в котором имена входных PDF-файлов (in_nn) называются ToC. Я написал скрипт на python, который читает имена, извлекает номера страниц и генерирует файл с именем pdfmarks. Слияние файлов легко выполняется с помощью gs. Точная команда выводится сценарием и должна выполняться отдельно (возможно, с некоторыми изменениями из-за изменений размера страницы или из-за операционной системы).

Вот. Возможно, некоторые изменения необходимы для Windows? (извините за комментарии не на английском языке). Просто запустите скрипт python в каталоге, где находятся PDF-файлы для слияния.

#!/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"

Сейда PDF (которая была предложена в одном из ответов) также доступна в виде онлайн-сервиса: https://www.sejda.com/merge-pdf.

Это может пригодиться, если вы не хотите устанавливать какое-либо дополнительное программное обеспечение и предпочитаете работать через Интернет из браузера.

Шаги для объединения:

  1. Перетащите все файлы PDF на веб-страницу
  2. По умолчанию все существующие закладки сохраняются и будут работать в объединенном документе.

  3. При желании инструмент слияния может создавать оглавление на основе объединяемых документов PDF.

Опция, выбранная для сгенерированного оглавления для объединенных документов PDF на основе имен файлов

Объединенное содержание PDF

Онлайн-сервис для слияния файлов PDF можно использовать до 30 файлов в час и до 50 МБ /200 страниц.

Отказ от ответственности: я - разработчик с открытым исходным кодом, работающий над Сейдой.

К сожалению, нет простого способа сделать это. Вы можете напрямую использовать библиотеку, на которой построен pdftk, и написать программу на Java или.NET, которая использует iText или iTextSharp для объединения ваших одностраничных пейджеров и создания закладок. Если вы хотите пойти по пути iText, есть много примеров, доступных онлайн или в книге iText (написанной автором iText).

... или, дайте мне знать, что не работает, и я могу помочь.

Есть PdfMod. Он имеет графический интерфейс и позволяет добавлять закладки вручную. Кроме того, если вы редактируете PDF, уже содержащий закладки, он автоматически обновит их, чтобы они указывали на правильные страницы.

Следующее предназначено, чтобы быть комментарием к ответу pdfmerger ( /questions/2517038/obedinit-pdf-s-pdftk-s-zakladkami/2517040#2517040).

Спасибо за ваш скрипт pdfmerger! Я знаю, что вопрос помечен как linux, но чтобы обобщить ваш скрипт для Mac OS X, нужно 2 вещи:

  • Ghostscript gs а также
  • команда pdfinfo (который включен, например, в poppler)

Установите их, получив первым brew (Google, он устанавливается с помощью команды 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]

писатель

(Установить с помощью pip install pystitcher)

pystitcher позволяет объединять PDF-файлы вместе, а также легко редактировать закладки, определяя окончательную структуру 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 .

Другие вопросы по тегам