12

Is there a possibility to get the total number of pages of an external PDF file within a LaTeX document?

Assuming that there exists a PDF file test.pdf with 8 pages in the same directory my LaTeX file is saved in. Here's my very basic approach:

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\usepackage{xparse}

\DeclareDocumentCommand \pdfnumberofpages { m } {
  % Do some magic
}

\begin{document}

\texttt{test.pdf}: \pdfnumberofpages{test.pdf} pages

\end{document}

The resulting document should then contain

test.pdf: 8 pages

I know it should be possible somehow (pdfpages must do something like this), but I don't know how to implement it.

13

After \tracingmacros1 with option pages=last-1, it seems like pdfpages uses a feature of pdf(la)tex to get the number.

\documentclass{minimal}
\begin{document}
    \pdfximage{test-29.pdf}
    \the\pdflastximagepages\ pages
\end{document}
  • That's really easy! Thank you! I also looked at pdfpages, but it was too much for me and I couldn't find the relevant command. – dawu Aug 27 '14 at 10:35
15

pdfTeX, LuaTeX

\pdflastximageages, see the answer of Symbol 1.

Remarks:

  • \pdfximage cannot be used in DVI mode.

LuaTeX

The number of pages can also be retrieved via the epdf Lua library:

\documentclass{article}

\newcommand*{\pdfnumberofpages}[1]{%
  \directlua{%
    local doc = epdf.open("\luatexluaescapestring{#1}")
    local pages
    if (doc) then
      pages = doc:getCatalog():getNumPages()
    else
      pages = 0
    end
    tex.write(pages)
  }%
}

\begin{document}
Number of pages: \pdfnumberofpages{test.pdf}
\end{document}

Remarks:

  • If the document does not exists, the macro \pdfnumberofpages returns zero.
  • \pdfnumberofpages is full expandable. Therefore it can be used in counter assignments, it can be written to a file, ...
  • It also works in DVI mode.

XeTeX

XeTeX provides \XeTeXpdfpagecount:

\documentclass{article}

\newcommand*{\numberofpages}[1]{%
  \the\XeTeXpdfpagecount"#1" %
}

\begin{document}
Number of pages: \numberofpages{test.pdf}
\end{document}

Remarks:

  • If the file does not exists, the result is zero.
  • Also this version if full expandable.

Summary

The following example puts the different versions together:

\documentclass{article}

\usepackage{ifpdf}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname XeTeXpdfpagecount\endcsname\relax
  \begingroup\expandafter\expandafter\expandafter\endgroup
  \expandafter\ifx\csname pdflastximagepages\endcsname\relax
    \newcommand*{\numberofpages}[1]{%
      0%
      \errmessage{\noexpand\numberofpages is unsupported for this driver}%
    }%    
  \else
    \ifpdf
      \newcommand*{\numberofpages}[1]{%
        \pdfximage{#1}%
        \the\pdflastximagepages
      }%
    \else
      \newcommand*{\numberofpages}[1]{%
        0%
        \errmessage{\noexpand\numberofpages is unsupported in DVI mode}%
      }%
    \fi
    \begingroup\expandafter\expandafter\expandafter\endgroup
    \expandafter\ifx\csname directlua\endcsname\relax
    \else
      \ifnum0\directlua{if epdf then tex.write(1)end}=1 %
        \renewcommand*{\numberofpages}[1]{%
          \directlua{%
            local doc = epdf.open("\luatexluaescapestring{#1}")
            local pages
            if doc then
              pages = doc:getCatalog():getNumPages()
            else
              pages = 0
            end
            tex.write(pages)
          }%
        }%
      \fi
    \fi 
  \fi
\else
  \newcommand*{\numberofpages}[1]{%
    \the\XeTeXpdfpagecount"#1" % space ends the file name scanning
  }%
\fi

\begin{document}
Number of pages: \numberofpages{test.pdf}
\end{document}

Remarks:

  • If the \newcommand and \renewcommand are replaced by \def constructs, then the definition also works in plain TeX. (\luatexluaescapestring might be available as \luaescapestring or has to be enabled via tex.enableprimitives.)
  • If the retrieval of the number of pages is not supported, an error message is thrown.
  • Wow, that's a really detailled answer! Thank you very much! Unfortunately, I only looked for pdflatex and that's why Symbol 1's answer is the best for me. It's too bad, that I only can accept one answer. But I voted you up! – dawu Aug 27 '14 at 10:38
  • 1
    UPDATE With LuaTEX version 1.10 the epdf library was replaced by the pdfe library (Reference Manual April 2019 p.257) Now, in order to get the total number of pages of an external pdf a couple of lines must be changed. For example function totalnopages(filename) local doc = pdfe.open(filename) if doc then local pages = doc.Pages local pagestotal = pdfe.getnofpages(doc) else pagestotal =0 end tex.write(pagestotal) end – Simon Dispa Aug 28 at 14:01
0

If someone is interested in a one-line command that writes the number of pages to the file test.pdf.pages (if test.pdf is the PDF file in question), the following (built upon the accepted answer) is working in command prompt under Windows 10 with MikTeX:

pdflatex "\documentclass{minimal}\nofiles\def\pdffile{test.pdf}\begin{document}\pdfximage{\pdffile}\newwrite\myfile\immediate\openout\myfile=\pdffile.pages\makeatletter\immediate\write\myfile{\the\pdflastximagepages}\makeatother\immediate\closeout\myfile\end{document}"

Together with test.pdf.pages, 2 unwanted files are generated: minimal.pdf and minimal.log, which can be deleted after compilation.

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.