2015-05-18 18 views
5

Sto cercando uno strumento da riga di comando per aggiungere segnalibri a un file PDF.Creare segnalibri in un file PDF tramite la riga di comando

Quello che ho è un page number e un label. Mi piacerebbe creare un segnalibro chiamato label che collega alla pagina page number.

Qualcuno conosce uno strumento da riga di comando (preferibilmente OSX) per farlo?

Ho circa 4000 pagine di file PDF e circa 150 segnalibri e mi piacerebbe automatizzarlo.

Il mio piano è utilizzare una chiamata di sistema all'interno di un r-script.

EDIT

creo circa 4000 file unico PDF con grafici e sto usando il comando di sistema OSX /System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py per unire i file PDF insieme. Precedentemente stavo usando pdfjoin dal pacchetto pdfjam, ma questo era troppo lento. Alla fine, questo è il modo in cui ottengo il mio PDF in cui aggiungo i segnalibri a mano con Adobe Acrobat Professional al momento.

+0

Non sono sicuro se si dispone del codice per produrre un PDF o solo il file PDF stesso. Se il primo, avremmo bisogno di molti più dettagli. – Roland

+0

Grazie a @Roland, ho aggiunto le informazioni sul tomo. – drmariod

+0

[pdftk] (https://www.pdflabs.com/docs/pdftk-version-history/) può aggiornare/inserire segnalibri. Inoltre, ecco una discussione potenzialmente utile su [stats.SO] (http://unix.stackexchange.com/questions/17065/add-and-edit-bookmarks-to-pdf) – hrbrmstr

risposta

3

È inoltre possibile utilizzare pdftk. È anche disponibile for OS X.

Non sto esaminando tutti i dettagli qui e ora, perché è già stato fatto altrove in maniera estesa. Brevemente:

  1. Creare un PDF di esempio dai file originali (senza segnalibri).
  2. Aggiungi alcuni segnalibri con Adobe Acrobat (a cui sembra avere accesso).
  3. Eseguire uno di questi comandi:

    pdftk my.pdf dump_data output - 
    pdftk my.pdf dump_data output bookmarks+otherdata.txt 
    
  4. Studio il formato dell'output.

  5. Modificare il file .txt di output aggiungendo tutte le voci desiderate.
  6. Run PDFTK ancora:

    pdftk my.pdf update_info bookmarks.txt output bookmarked.pdf 
    

Informazioni aggiuntive

Questo è il formato segnalibro che ho notato dopo aver ispezionato al precedente punto 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... 

E sostituire quanto sopra .. nel punto appropriato.

+0

In realtà, mi piace molto questa soluzione, una sintassi molto chiara e molto facile da scrivere ... Grazie – drmariod

+0

@drmariod: In realtà, mi piace questa soluzione * meno * di tutti e tre :) –

+0

mi piace questa soluzione la migliore e la più semplice posso capire ... come ho già fatto. – ihightower

1

Ok, ecco un modo frettoloso e approssimativo di fare tre lavori contemporaneamente:

  1. unire i 400 file PDF a pagina singola.
  2. Creare un documento di livello superiore ToC (Table of Contents).
  3. Creare un segnalibro PDF per ogni pagina.

Comprende l'installazione di LaTeX.

Si inizia con un modello di LaTeX vuoto come la seguente:

\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} 

Ora appena prima l'ultima linea di questo modello, si inserisce una riga per file PDF esterno che si desidera includere.

  1. Nel caso in cui si desidera generare un indice, deve essere formattato in questo modo:

    \includepdf[pages={<pagenumber>},addtotoc{<pagenumber>,<section>,<level>,\ 
            <heading>,<label>}]{pdffilename.pdf} 
    
  2. Nel caso in cui si è certi che tutti e ciascuno compreso PDF è un documento di 1 pagina, semplifica a questo:

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

Qui tutto dei seguenti cinque parametri per addtotoc, nell'ordine in cui i file vengono visualizzati nei segnalibri e nel ToC. Vedere più sotto per un esempio specifico:

  • <pagenumber>: numero della pagina del documento inserito per essere collegati a. (Nel tuo caso sempre "1", perché inserisci solo documenti di una sola pagina, però puoi inserire un documento di 5 pagine e collegarti alla pagina 3 del PDF inserito).
  • <section>: il nome di sezione LaTeX. Potrebbe essere section, subsection, subsubsection ... Nel tuo caso "sezione".
  • <level>: il livello della sezione LaTeX. Nel tuo caso "1".
  • <heading>: Questa è una stringa. Utilizzato per il testo del segnalibro
  • <label>: deve essere univoco per ciascun segnalibro. Utilizzato nel PDF internamente per saltare alla pagina corretta quando si fa clic sul segnalibro.

Per verificare questa fretta, ho usato Ghostscript per generare 20 documenti PDF di 1 pagina:

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 

Con questi file di test ho potuto fare le linee per inserire nel look modello di come questi:

\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} 

Salvare il modello con le linee inserite, quindi eseguire il seguente comando due volte:

pdflatex template.tex 
pdflatex template.tex 

Il file risultante avrà i segnalibri, guardando come questo in Preview.app:

Screenshot: Preview.app with the bookmarks opened


Nota: LaTeX è disponibile per OSX attraverso due metodi:


io aggiungo uno o due altri metodi per inserire i segnalibri sulla riga di comando troppo tardi o nei prossimi giorni, se ho più tempo.

Per ora questo si deve fare, perché non ho mai mostrato qui su SO, AFAICR.

Ma ho pensato, perché hai dato lo sfondo "Sto Merging PDF 1 pagine, ed è lento, ora voglio aggiungere segnalibri troppo ...", ho potuto mostrare come farlo con un solo metodo.

SUGGERIMENTO: Uno degli altri metodi sarà quello di utilizzare pdftk che IS disponibile per Mac OS X!

+0

Non riesco a ottenere il comando' addtotoc' in esecuzione ... Dice il comando non viene trovato, ma può trovare il pacchetto 'pdfpages' ... Quindi non capisco il problema qui :-( – drmariod

+0

@dmariod: Senza vedere il tuo codice non posso dire cosa c'è che non va. molto semplice che gli stessi occhi che fissavano la/e riga/e durante la scrittura non sono più in grado di riconoscere, ma gli occhi di "terze parti" possono facilmente ... anche a me è successo, e non solo una volta :) –

2

Ecco un'altra risposta. Questo utilizza Ghostscript per elaborare PDF-to-PDF e l'operatore pdfmark PostScript per inserire i segnalibri.

Per alcuni introduzione al tema pdfmark, vedi anche:

Questo metodo comporta due fasi:

  1. creare un file di testo (un file PostScript, in realtà), con una serie limitata di pdfmark comandi, uno per riga e segnalibro che si desidera aggiungere.
  2. Eseguire il comando Ghostscript che elabora il file PDF corrente insieme al file di testo.

1.

Il contenuto del file di testo dovrebbe essere simile a questo:

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

Nome questo file, ad esempio: addmybookmarks.txt

2.

ora gestita questo comando:

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

Il PDF risultante, bookmarked.pdf contiene ora i segnalibri. Vedere questo screenshot:

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

1

Ecco il metodo python per aggiungere segnalibri al sommario. Funziona su MacOS senza altre installazioni.

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