[Tex/LaTex] Compiling only a page range or page selection

compiling

How do I easily compile only a page range or page selection? That is, I would like a document that

  • looks exactly like the full document,
  • has only the subset of pages that were manually chosen, by page number (this can be one contiguous range or a more complicated selection, like "12-15,23,45-49"),
  • has correct page numbers, and
  • has correct links, except links to missing pages should be either dysfunctional or absent.

Best Answer

atbegshi provides the capability to discard a ready-to-be-shipped-out page using \AtBeginShipoutDiscard. Together with etoolbox's list-processing capability, you can easily discard/retain pages conditionally:

\documentclass{article}
\usepackage{lipsum,atbegshi,etoolbox}% http://ctan.org/pkg/{lipsum,atbegshi,etoolbox}
\makeatletter
\newcommand{\discardpages}[1]{% \discardpages{<csv list>}
  \xdef\discard@pages{#1}% Store pages to discard
  \AtBeginShipout{% At shipout, decide whether to discard page/not
    \renewcommand*{\do}[1]{% How to handle each page entry in csv list
      \ifnum\value{page}=##1\relax%
        \AtBeginShipoutDiscard% Discard page/not
        \gdef\do####1{}% Do nothing further
      \fi%
    }%
    \expandafter\docsvlist\expandafter{\discard@pages}% Process list of pages to discard
  }%
}
\newif\ifkeeppage
\newcommand{\keeppages}[1]{% \keeppages{<csv list>}
  \xdef\keep@pages{#1}% Store pages to keep
  \AtBeginShipout{% At shipout, decide whether to discard page/not
    \keeppagefalse%
    \renewcommand*{\do}[1]{% How to handle each page entry in csv list
      \ifnum\value{page}=##1\relax%
        \keeppagetrue% Page should be kept
        \gdef\do####1{}% Do nothing further
      \fi%
    }%
    \expandafter\docsvlist\expandafter{\keep@pages}% Process list of pages to keep
    \ifkeeppage\else\AtBeginShipoutDiscard\fi% Discard page/not
  }%
}
\makeatother
\discardpages{1,3,5,7,9,29,35,40}% Discard these pages.
%\keeppages{2,4,6}% Keep these pages.
\begin{document}
\lipsum[1-50]\lipsum[1-50]\lipsum[1-50]\lipsum[1-50]\lipsum[1-50]
\end{document} 

The above 47-page document is scaled down to 39 after having removed the 8 pages 1, 3, 5, 7, 9, 29, 35, 40 (as supplied by \discardpages{1,3,5,7,9,29,35,40}). To discard zero pages, you could use \discardpages{} (or make no call to \discardpages). Using \keeppages{2,4,6} instead leaves you with a 3-page document consisting of only pages 2, 4 and 6. It should not be that difficult to extend this to include more complicated page ranges.

The above has not been tested with hyperlinks from hyperref.