155

I'd like to be able to create a TeX file that will output multiple PDF files with one compilation. I'm not even sure if this is possible. Here is the setup:

I am writing dozens of cover letters for job applications, and wish for them to all look "personalized". So I defined a function which calls multiple variables, such as the address, name of the institution, open position, etc., and outputs a "personalized" cover letter for each function call. The problem is that compilation of the TeX file outputs just one file. Since I will be submitting all of these files online eventually, I would like each letter to be in its own file. Is there a way to do this at the TeX level?

11
  • 24
    Another use for this kind of thing would be to have one compile command output a beamer slides pdf and a handout pdf...
    – Seamus
    Nov 11, 2010 at 20:57
  • What operating system are you on? A simple batch file or script could be made to do what you want easily enough.
    – frabjous
    Nov 11, 2010 at 21:06
  • 9
    probably easier to write a makefile/script that regex's the necessary "personalized" parts then generates the file and compiles it to PDF.
    – Mica
    Nov 11, 2010 at 21:46
  • 1
    I use the plain letter class and pdftk. Nov 12, 2010 at 2:52
  • 1
    This is also useful for sending your phdthesis.pdf through email with size limitations.
    – Trevis
    Jan 9, 2014 at 18:05

9 Answers 9

60

How do you store this information? You could just have one info-file for each letter

% letter1.adr
\def\toname{Foo}

and

% letter2.adr
\def\toname{Bar}

and then have a main file

% main.tex
\documentclass[addrfield]{scrlttr2}
\input \jobname.adr

\begin{document}
\begin{letter}{\toname}
\opening{Dear \toname, }
 A nice letter.
\end{letter}
\end{document}

Then you can compile all letters from the command line with something like

for %i in (*.adr) do pdflatex -jobname=%i main.tex

The koma bundle also provides tools for more sophisticated address files.

3
  • 1
    I've been using essentially this trick for years, to ensure that items charged on invoices match up with the work specified in contracts. Nov 11, 2010 at 21:15
  • I do the same except I use a makefile for managing the dependencies and rebuilds.
    – Pat Notz
    Nov 11, 2010 at 21:53
  • This was just what I was looking for; thanks!
    – Kristen
    Nov 12, 2010 at 17:47
55

Yes it is possible if you enable \write18 (e.g. pdflatex --shell-escape with MiKTeX). Then you can call pdflatex again inside your document. An example (the code is not from me). It will generate three documents \jobname1-\jobname3:

Case insensitive operating systems (e.g. Windows/MacOS)

\documentclass{article}

\ifx\conditionmacro\undefined
  \immediate\write18{%
    pdfLaTeX --jobname="\jobname1"
    \gdef\string\conditionmacro{1}\string\input\space\jobname
  }%
  \immediate\write18{%
    pdfLaTeX --jobname="\jobname2"
    \gdef\string\conditionmacro{2}\string\input\space\jobname
  }%
  \immediate\write18{%
    pdfLaTeX --jobname="\jobname3"
    \gdef\string\conditionmacro{3}\string\input\space\jobname
  }%
  \expandafter\stop
\fi

\begin{document}
\ifnum\conditionmacro=1 Condition is 1\fi
\ifnum\conditionmacro=2 Condition is 2\fi
\ifnum\conditionmacro=3 Condition is 3\fi

\verb|\conditionmacro| is \texttt{\meaning\conditionmacro}.
\end{document}

Case sensitive operating systems (e.g. Linux)

As noted in Martin Heller's comment you need to change this code for case sensitive operating systems to:

\documentclass{article}

\ifx\conditionmacro\undefined
  \immediate\write18{%
    pdflatex --jobname="\jobname1"
    "\gdef\string\conditionmacro{1}\string\input\space\jobname"
  }%
  \immediate\write18{%
    pdflatex --jobname="\jobname2"
    "\gdef\string\conditionmacro{2}\string\input\space\jobname"
  }%
  \immediate\write18{%
    pdflatex --jobname="\jobname3"
    "\gdef\string\conditionmacro{3}\string\input\space\jobname"
  }%
  \expandafter\stop
\fi

\begin{document}

\ifnum\conditionmacro=1 Condition is 1\fi 

\ifnum\conditionmacro=2 Condition is 2\fi

\ifnum\conditionmacro=3 Condition is 3\fi

\verb|\conditionmacro| is \texttt{\meaning\conditionmacro}.

\end{document}

Edit for lualatex

in newer luatex version \write18 has no special meaning anymore and can't be used like this. You then need the shellesc package which overloads \write. It also offers a \ShellEscape which can be used (also with pdflatex) instead of the primitive commands. The example looks then like this.

\documentclass{article}
\usepackage{shellesc}
\ifx\conditionmacro\undefined
  \ShellEscape{%
    lualatex --jobname="\jobname1"
    "\gdef\string\conditionmacro{1}\string\input\space\jobname"
  }%
  \ShellEscape{%
    lualatex --jobname="\jobname2"
    "\gdef\string\conditionmacro{2}\string\input\space\jobname"
  }%
  \ShellEscape{%
    lualatex --jobname="\jobname3"
    "\gdef\string\conditionmacro{3}\string\input\space\jobname"
  }%
  \expandafter\stop
\fi

\begin{document}

\ifnum\conditionmacro=1 Condition is 1\fi

\ifnum\conditionmacro=2 Condition is 2\fi

\ifnum\conditionmacro=3 Condition is 3\fi

\verb|\conditionmacro| is \texttt{\meaning\conditionmacro}.

\end{document}
8
  • 2
    Very nice. On case sensitive systems you need to use lowercase for the call to pdflatex. I also had to add quotes around the \gdef.... Nov 12, 2010 at 22:47
  • 2
    I know it's old but --- thanks. I use to prepare multiple versions of tests and exams and this helps me a lot. Now I will try to search how to make this work with latexmk....
    – Rmano
    Apr 4, 2014 at 15:37
  • while this is an interesting, surprising, and working solution, it works essentially like an external script calling n different, precompiled tex sources. specifically, the overhead of getting LaTeX up and running—load all the packages needed—is present for each single pdf produced. that means a solution which first produces a multiple-page pdf that is then split into single pages might be more performant.
    – flow
    Nov 23, 2014 at 20:26
  • @flow: This one starts multiple instances that will run in parallell, right? For larger documents I am guessing the overhead of starting up is much smaller than the actual work of compiling so on todays multitasking monster machines I am guessing this might in fact instead be faster. At least for larger projects... yes / no?
    – jonalv
    Jun 18, 2015 at 8:43
  • It generates main1 main2 main3`. Is there a solution to name the output pdfs?
    – CroCo
    Nov 20, 2015 at 1:43
30

The answer is no, TeX outputs one PDF file.

I'd use a tool to split the PDF files afterwards. pdfpages (TeX) pdfsam, and pdftk should do the trick.

2
  • 1
    If have found pdftk to be cumbersome if you want to split a PDF into k-page chunks for k>1. So, naturally, I wrote a script to do it more conveniently.
    – Raphael
    Sep 9, 2013 at 12:35
  • 1
    Pdfsam (which is in Debian's depot) and its "split by bookmark level" option is really nice. Good job, simple to use, perfect.
    – Clément
    Nov 20, 2016 at 20:55
10

I know this is an old question, but here is an alternative approach, based on an idea from Automatically create two PDF output files from one tex file [duplicate]

The idea is to write at begin of each chapter some commands (including the page numbers where to split the pdf) in a batch-file and after LaTex has finished, run the script to split the pdf into multiple files (using pdftk).

\documentclass[10pt,a4paper]{report}
\usepackage[latin1]{inputenc}
\usepackage{pageslts} %  theCurrentPage
\usepackage{calc} % theCurrentPage+1
\usepackage{blindtext} % Lorem ipsum dolor ...

\newcounter{FirstPage} % counter, for first page number
\setcounter{FirstPage}{1} % Set FirstPage to page 1

\newwrite\BatchFile% Batch-Datei
\immediate\openout\BatchFile=BatchFile.txt% *.bat don't work

\newcommand{\Split}[1]{%
\immediate\write\BatchFile{pdftk.exe\space \jobname.pdf\space cat \theFirstPage -\theCurrentPage\space output\space \jobname-#1.pdf dont_ask}% 
\setcounter{FirstPage}{\theCurrentPage+1}% set FirstPage to new first page
}
\begin{document}
\pagenumbering{arabic} % for pageslts

\chapter{One}

\Blindtext 

\Split{C1} % Split for Chapter 1  
%--------------------------------------------------------------
\chapter{Two}

\Blindtext\Blindtext

\Split{C2} % Split for Chapter 2
%--------------------------------------------------------------
\chapter{Three}
\setcounter{page}{1} % Chapter 3 with new page numbers

\Blindtext \Blindtext \blindtext 

\Split{C3} % Split for Chapter 3
%==========================
\immediate\write\BatchFile{exit}% 
\immediate\closeout\BatchFile% 
\immediate\write18{cmd /c move BatchFile.txt BatchFile.bat} % rename Batch File
\end{document}

I know the solution can be improved, for example merge the \Split with the \chapter command or do the stuff at the end automatically.

2
  • Welcome to TeX.SX! May 4, 2015 at 10:45
  • I'm amused that you've linked to a post that is closed as a duplicate of this question. But more importantly, I think this will only work if you're splitting chapters or similar documents. If you want to have different \documentclass, for example, this approach won't work.
    – Teepeemm
    Jul 6, 2017 at 0:21
6

You can do as Patrick says, or you can generate TeX files from a script language (say, Perl + Template Toolkit) and then use environment variables to pass the parameters.

E.g. on Linux with bash, you can do $ PARAM1=VALUE1 PARAM2=VALUE2 perl ./compile.pl

3
  • 1
    +1 for Perl + TT (search.cpan.org/~abw/Template-Toolkit-2.22/lib/Template.pm), but why pass parameters on env variables? In the script that will do the compiling just have a hash of the data needed and foreach of the keys do a replace/compile Nov 12, 2010 at 13:44
  • 1
    Wouldn't it be easier to use something along the lines of awk or sed to do a replacement?
    – Canageek
    Sep 28, 2011 at 4:38
  • 1
    @Canageek, it's just my prejudice against editing the code when I can use inputs :) Sep 28, 2011 at 7:44
4

I don't think you can make a single .tex file produce multiple .PDFs, however you could create some very simple .tex files (one per PDF you want to create), which simply set up a few macros (your personalised variables) and then \input (or \include) the common .tex file.

Running pdflatex (or whatever TeX-to-xxx converter/compiler you like best) on each of the small files will produce all your PDFs.

(Probably worth writing a little script to compile each one if the differing elements are more than very simple macro replacements)

4

Expanding on my comment to Alexei, If you make a file test.tex with:

\documentclass{article}

\begin{document}

Hello [% name %]

\end{document}

and a test.pl with:

#!/usr/bin/env perl

use strict;
use warnings;

use Template;

my $tt = Template->new(); 

my @names = ('john','sally');
my $infile = 'test.tex';

foreach my $name (@names) {
  my %data;
  my $outname = $name . 'tex';
  $data{'name'} = $name;
  $tt->process($infile,\%data, $outname);
  system("latexmk -pdf $outname");
  system("latexmk -c");
}

when you execute test.pl you should get a john.tex and a john.pdf, etc in the same folder. Its a simple example but I'm sure you can extend it to what you need. PS if you don't know latexmk, check it out!

2

You should be able to do this with the letter options in KOMA script, it's briefly in the manual although I haven't personally experimented with it.

1

Since cover letter usually does not exceed 1 page, it is possible to extract given range of pages from Adobe Acrobat using Tools | Pages | Extract | Extract Pages As Separate Files.

You must log in to answer this question.

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