Создание закладок в PDF-файл с помощью командной строки

Я ищу инструмент командной строки для добавления закладок в файл PDF.

у меня есть page number и label. Хотелось бы создать закладку под названием label ссылка на страницу page number.

кто-нибудь знает инструмент командной строки (предпочтительно OSX) для этого?

у меня есть около 4000 страниц PDF-файлов и около 150 закладок, и я хотел бы автоматизировать его.

мой план заключается в использовании системного вызова в Р-сценарий.

редактировать

Я создаю около 4000 отдельных PDF-файлов с графиками, и я использую системную команду OSX /System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py для объединения PDF-файлов вместе. Ранее я использовал pdfjoin С pdfjam пакета, но это было слишком медленно. В конце концов, именно так я получаю свой PDF, где я добавляю закладки вручную с помощью Adobe Acrobat Professional на данный момент.

4 ответов


вы также можете использовать pdftk. Он также доступен для OS X.

Я не буду обсуждать все детали здесь и сейчас, потому что это уже было сделано в другом месте. Только коротко:

  1. создайте образец PDF из исходных файлов (без закладок).
  2. добавить некоторые закладки с Adobe Acrobat (к которым у вас, похоже, есть доступ).
  3. запустить один из этих команд:

    pdftk my.pdf dump_data output -
    pdftk my.pdf dump_data output bookmarks+otherdata.txt
    
  4. изучите формат вывода.

  5. изменить выход .txt файл, добавив все записи, которые вы хотите.
  6. запустите PDFTK еще раз:

    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...

и заменить выше.. в нужном месте.


хорошо, вот быстрый способ сделать три работы сразу:

  1. объединить 400 одностраничных PDF-файлов.
  2. создайте документ верхнего уровня ToC (Оглавление).
  3. создайте закладку PDF для каждой страницы.

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

  1. если вы хотите создать ToC, он должен быть отформатирован следующим образом:

    \includepdf[pages={<pagenumber>},addtotoc{<pagenumber>,<section>,<level>,\
                       <heading>,<label>}]{pdffilename.pdf}
    
  2. в случае, если вы уверены, что каждый включенный PDF является 1-страничным документом, он упрощает это:

    \includepdf[addtotoc{<pagenumber>,<section>,<level>,\
                         <heading>,<label>}]]{pdffilename.pdf}
    

здесь все из следующих пяти параметров для addtotoc требуются в порядке, указанном для файлов, чтобы отображаются в закладках и в ToC. См. ниже конкретный пример:

  • <pagenumber>: номер страницы вставленного документа, с которым необходимо связать. (В вашем случае всегда "1", потому что вы вставляете только 1-страничные документы; вы можете вставить 5-страничный документ и ссылку на страницу 3 вставленного PDF).
  • <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

полученный файл будет иметь закладки, выглядящие так в предварительном просмотре.app:

Screenshot: Preview.app with the bookmarks opened


Примечание: латекс доступно для OSX двумя способами:


я добавлю один или два других метода для вставки закладок в командной строке, позже или в ближайшие несколько дней, если у меня будет больше времени.

пока это нужно сделать, потому что я никогда не показывал его здесь на SO, AFAICR.

но я думал, потому что вы дали фон " я объединяю 1-страничные PDF-файлы, и это медленно; теперь я хочу добавить закладки тоже...- Я мог бы показать, как это делается одним-единственным способом.

подсказка : один из других методов можно будет использовать pdftk, который IS доступно для Mac OS X!


вот еще один ответ. Этот использует Ghostscript для обработки PDF-to-PDF и pdfmark оператор PostScript для вставки закладок.

для некоторого введения в тему pdfmark см. Также:

этот метод включает в себя два шага:

  1. создайте текстовый файл (Файл PostScript, действительно) с ограниченным набором из pdfmark команды, по одной на строку и закладку, которую вы хотите добавить.
  2. запустите команду Ghostscript, которая обрабатывает текущий PDF-файл вместе с текстовым файлом.

1.

содержимое текстового файла должно выглядеть примерно так:

[/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

2.

теперь выполните следующую команду:

gs -o bookmarked.pdf   \
   -sDEVICE=pdfwrite   \
    addmybookmarks.txt \
   -f original.pdf

полученный PDF,bookmarked.pdf теперь содержит закладки. Видеть этот скриншот:

Screenshot of bookmarks added with the help of Ghostscript and <code>pdfmark</code>


вот метод 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)