18

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.

1

4 Answers 4

19

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}
2
  • 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, 2014 at 10:35
  • To the reader: Contrary to what one might expect, \pdfximage does not embed the pdf as an image. The document shown compiles to an empty page with the text … pages – just as I wanted :)
    – Socowi
    Nov 9, 2019 at 13:07
24

pdfTeX, LuaTeX

\pdflastximageages, see the answer of Symbol 1.

Remarks:

  • \pdfximage cannot be used in DVI mode.

LuaTeX

Unhappily, LuaTeX is constantly changing its interfaces. \luatexluaescapestring was renamed to \luaescapestring and the library epdf was replaced by the library pdfe. The following example was developed and tested with 1.15.0.

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

\documentclass{article}

\newcommand*{\pdfnumberofpages}[1]{%
  \directlua{%
    local doc = pdfe.open("\luaescapestring{#1}")
    local pages
    if (doc) then
      pages = pdfe.getnofpages(doc)
    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.

Older 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}
% XeTeX check
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname XeTeXpdfpagecount\endcsname\relax
  % pdfTeX check
  \begingroup\expandafter\expandafter\expandafter\endgroup
  \expandafter\ifx\csname pdflastximagepages\endcsname\relax
    \newcommand*{\numberofpages}[1]{%
      0%
      \errmessage{\noexpand\numberofpages is unsupported for this driver}%
    }%    
  \else
    % Definition for pdfTeX
    \ifpdf
      \newcommand*{\numberofpages}[1]{%
        \pdfximage{#1}%
        \the\pdflastximagepages
      }%
    \else
      \newcommand*{\numberofpages}[1]{%
        0%
        \errmessage{\noexpand\numberofpages is unsupported in DVI mode}%
      }%
    \fi
  \fi
  % LuaTeX check
  \typeout{LuaTeX check}
  \begingroup\expandafter\expandafter\expandafter\endgroup
  \expandafter\ifx\csname directlua\endcsname\relax
  \else
    \begingroup\expandafter\expandafter\expandafter\endgroup
    \expandafter\ifx\csname luaescapestring\endcsname\relax
      \typeout{luaescapestring is undefined}%
      \begingroup\expandafter\expandafter\expandafter\endgroup
      \expandafter\ifx\csname luatexluaescapestring\endcsname\relax
      \typeout{luatexluaescapestring is undefined}%
      \else
        \newcommand*{\LuaEscapeString}{}%
        \let\LuaEscapeString\luatexluaescapestring
      \fi
    \else
      \newcommand*{\LuaEscapeString}{}%
      \let\LuaEscapeString\luaescapestring
    \fi
    \begingroup\expandafter\expandafter\expandafter\endgroup
    \expandafter\ifx\csname LuaEscapeString\endcsname\relax
    \else
      % Definition for newer LuaTeX
      \ifnum0\directlua{if pdfe then tex.write(1)end}=1 %
        \renewcommand*{\numberofpages}[1]{%
          \directlua{%
            local doc = pdfe.open("\LuaEscapeString{#1}")
            local pages
            if (doc) then
              pages = pdfe.getnofpages(doc)
            else
              pages = 0
            end
            tex.write(pages)
          }%
        }%
      \else
        % Definition for older LuaTeX
        \ifnum0\directlua{if epdf then tex.write(1)end}=1 %
          \renewcommand*{\numberofpages}[1]{%
            \directlua{%
              local doc = epdf.open("\LuaEscapeString{#1}")
              local pages
              if (doc) then
                pages = doc:getCatalog():getNumPages()
              else
                pages = 0
              end
              tex.write(pages)
            }%
          }%
        \fi
      \fi
    \fi
  \fi
\else
  % Definition for XeTeX
  \newcommand*{\numberofpages}[1]{%
    \the\XeTeXpdfpagecount"#1" % space ends the file name scanning
  }%
\fi

\begin{document}
Number of pages: \numberofpages{test.pdf}% Should be different from \jobname.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.
8
  • 1
    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, 2014 at 10:38
  • 2
    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 Aug 28, 2019 at 14:01
  • Can you update your answer for the latest versions of TeXLive (2022)? Thanks. Apr 19, 2022 at 8:24
  • @SimonDispa Thanks. The constant changing of the interfaces in LuaTeX is quite annoying. Apr 20, 2022 at 17:33
  • @PaulGaborit I have updated the answer for LuaTeX 1.15.0. Apr 20, 2022 at 17:33
3

With a current l3graphics (currently in l3experimental) you can use \graphics_get_pagecount:nN to retrieve the page count and then either print it or use it as page number in a \includegraphics command. \graphics_get_pagecount:nN works with all engines and also with LaTeX in dvi mode.

\documentclass{article}
\usepackage{l3graphics}
\usepackage{graphicx}
\begin{document}

\ExplSyntaxOn
\graphics_get_pagecount:nN {example-image-a4-numbered.pdf}\l_tmpa_tl
\l_tmpa_tl
\includegraphics[scale=0.5,page=\l_tmpa_tl]{example-image-a4-numbered.pdf}
\ExplSyntaxOff

\end{document}

enter image description here

1
  • Fantastic. Thank you for this simple and general solution. Apr 21, 2022 at 5:27
-1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .