7

How can I list the named destinations in a PDF file?

Named destinations are the formal name for what you might call anchors. Major browsers jump to the named destination foo when you follow a link to http://example.com/some.pdf#foo.

I have documents where I can see anchors working, but I can't seem to find a way to list the anchors. Evince, okular and xpdf will jump to them when instructed but don't seem to have an interface that lists them. pdftk dump_data lists bookmarks, but that's not the same thing (that's table of content entries, which may well be at the same position as named destinations but can't be used as anchors).

I'm looking for a command line solution (suitable, for example, for use in a completion function after the likes of evince -n). Inasmuch as this is meaningful, I'd like to list the destinations in the order in which they appear in the document. Bonus: show the target page number and other information that helps figure out approximately where the destination is.

See also View anchors in a PDF document on Software Recommendations for a GUI viewer.

6

Poppler's pdfinfo command-line utility will provide you with page number, position, and name for all named destinations in a PDF. You need at least version 0.58 of Poppler.

$ pdfinfo -dests input.pdf
Page  Destination                 Name
   1 [ XYZ null null null      ] "F1"
   1 [ XYZ  122  458 null      ] "G1.1500945"
   1 [ XYZ   79  107 null      ] "G1.1500953"
   1 [ XYZ   79   81 null      ] "G1.1500954"
   1 [ XYZ null null null      ] "P.1"
   2 [ XYZ null null null      ] "L1"
   2 [ XYZ null null null      ] "P.2"
(...)
1

This prints them (twice) sorted by name and then by page position down the pdf. A large sample pdf containing named-destinations

#!/usr/bin/env python
import sys
from pyPdf import PdfFileReader
def pdf_get_anchors(fh):
    reader = PdfFileReader(fh)
    destinations = reader.getNamedDestinations()                #completely unsorted order, does not include pagenums
    L=list();
    for PageNum in range(1,reader.numPages+1) :
        ThisPage = reader.getPage(PageNum-1)
        PageTop = ThisPage['/MediaBox'][3]
        for name in destinations:
            ThisDest = destinations[name]
            ThisDestPage = ThisDest.page.getObject()
            if ThisDestPage == ThisPage:                        #have to do this to identify the pagenum
                DownPage = (PageTop - ThisDest.top) / PageTop   # calc fraction of page down
                Position = PageNum + DownPage                   # a sortable number down the whole pdf
                L.append((name, PageNum, Position));            # put everything in a sortable list         
    return L, len (destinations), reader.getNumPages()

def pdf_print_anchors ( L ) :
    for dest in L :
        name=dest[0]
        PageNum=dest[1]
        Position= round(dest[2]*100)/100
        print "%-8.2f % %s" % Position % name #ThisDest.title
        #print ThisDest.title, "       ",  PageNum,  round(Position*100)/100

HeaderLine="\n Page   Name\n"                     
L, NumDests, NumPages =pdf_get_anchors(open(sys.argv[1],'rb'))
print HeaderLine
L.sort(key=lambda dest: dest[0])                        #sort name order
pdf_print_anchors(L);     
print HeaderLine
L.sort(key=lambda dest: dest[2])                        #sort in order down the pdf
pdf_print_anchors(L);
print HeaderLine
print "Number of NamedDestinations: ", NumDests, "NumPages: ", NumPages
  • 1
    Your answer builds on the work of an earlier one. That's permitted, but you should acknowledge it. – JigglyNaga Jul 30 '16 at 8:56
  • 2
    My initial reply simply bug fixed the original, I would have thought that rather self evident, and certainly did not purport to be anything. – Henry Crun Jul 30 '16 at 9:02
7

The pyPDF library can list anchors:

#!/usr/bin/env python
import sys
from pyPdf import PdfFileReader
def pdf_list_anchors(fh):
    reader = PdfFileReader(fh)
    destinations = reader.getNamedDestinations()
    for name in destinations:
        print name
pdf_list_anchors(open(sys.argv[1]))

That's good enough for the completion use case, but the anchors are listed in a random order. With only the stable interfaces of pyPdf 1.13, I can't find a way to list the anchors in order. I haven't tried pyPdf2 yet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.