# Script to automate externalizing TikZ graphics

Is there a script to automate externalizing TikZ graphics?

(As suggested by Scott here)

-
possible duplicate of Automagically externalising pdftricks and TikZ pictures – Sharpie Aug 13 '10 at 23:19
Yes, but the answers here are better. – Neil G Aug 14 '10 at 3:46

The TikZ 2.10 library, external, addresses this issue. Externalizing all TikZ graphics in a LaTeX document is as easy as:

\usetikzlibrary{external}
\tikzexternalize


If your document is named report.tex, this will dump out a series of images: report-figure0.pdf, report-figure1.pdf, etc, etc. To get a more manageable output, you can specify a directory for in which the files are to be placed and names that are more descriptive than report-figure0.pdf:

\usetikzlibrary{external}
\tikzexternalize[prefix=figures/]

% Rest of preamble
% Begin document, write stuff

% Set a filename for the next tikzpicture.
\tikzsetnextfilename{importantFigure}
\begin{tikzpicture}  % This will be output to figures/importantFigure.pdf
% Picture code
\end{tikzpicture}


To compile the document, you will need to ensure the figures directory exists and run pdflatex with shell execution enabled:

mkdir figures
pdflatex -shell-escape <tex file>


A whole pile of options is available to customize the way the figures are output. See section 31.4 (this numbering is subject to change!) of the development version documentation for complete info and options. The manual also covers how to obtain EPS output- but this option looks less polished than PDF output.

-
+1 for "ramming a flaming stick into your eyeball" ;-) – Giel Aug 10 '10 at 13:19
Typo: you use a dollar for a comment after the \begin{tikzpicture}. – Loop Space Sep 19 '10 at 19:48
Checking out with CVS is more fun than trying to contribute back with CVS, I think. Though I've been shying away from it lately as I can't bring myself to use a non-distributed VCS directly anymore :-), and it's unlikely that there is a DVCS that can pull from CVS do to it's lack of atomicity :-(. – SamB Dec 19 '10 at 5:36
Wow, this produces … “interesting” crashes (spurious, random “file ended prematurely” messages etc.) when used together with e.g. todonotes, which also uses TikZ under the hood. I’ve tried conditionally enabling that package and disabling externalization for the to do entries – to no avail. – Konrad Rudolph Jan 29 '11 at 19:34
This external library is now available as part of PGF 2.10. – Faheem Mitha Feb 26 '11 at 21:20

I’ve just come up with the following. It seems to work quite well (on Unix/Linux and Mac):

SOURCE=$1 for name in$( \
grep '^[:space:]*\\beginpgfgraphicnamed' $SOURCE | \ sed s'/[:space:]*\\beginpgfgraphicnamed{$$.*$$}/\1/' \ ); do pdflatex --jobname=$name $SOURCE done  An explanation: It uses grep to filter out all lines that contain \beginpgfgraphicsnamed, but only if there’s only whitespace before the command in the line. This prevents that commented-out commands are also found. Next, it invokes sed to filter from those lines only the relevant part, i.e. the command argument that’s to be used as the pdflatex jobname. It then uses for to iterate over all these jobnames and calls pdflatex in turn for each of them. - Here's my alternative; Konrad's answer is probably just as good, and certainly better documented. for job in grep -o beginpgfgraphicnamed\{[0-9A-Za-z-]*\} <$1 | sed -e 's/beginpgfgraphicnamed{//' | sed -e 's/}//'; do
pdflatex --jobname $job$1;
rm $job.log; rm$job.out;
}

\immediate\openin\myscriptresult=pdfscreated.res
\immediate\closein\myscriptresult

\ifnum\ScriptResult>0
\stop
\fi


The image is included like this in a (very short) main document:

\documentclass{article}
\usepackage{imgs} % see code above!
\usepackage{header} % may be the same as for images, or different, as you like
\begin{document}
\includegraphics{\imgs\imga.pdf}
\end{document}


An example for an image would be

\documentclass[10pt]{article}
\usepackage{../header} % own header for images, may be the same as for main document or not...
\begin{document}
\thispagestyle{empty}
\begin{tikzpicture}
%draw sthg...
\draw (0,0) -- (1,1);
\end{tikzpicture}
\end{document}


And the called shell script (which could easily be replaced by perhaps nicer solutions like the python script by pmav99) looks like the following:

#!/bin/bash

# first argument contains folder of .tex-files
cd $1 shift # counting the number of pdfs, e.g. for the laiter waiting for pids cnt=0 # relevant files and commands header="../header.sty" texbin="lualatex --shell-escape " pdfcrop=pdfcrop if [ ! -e$header ] ; then
echo "$header doesn't exists. This is bad." exit 3 fi while [[$# > 0 ]] ; do
cnt=$(($cnt+1))
tex="$1.tex" pdf="$1.pdf"
names[$cnt]="$1" # store name for later error messages and pdfcrop

if [ ! -e $tex ] ; then echo "$tex doesn't exists. Maybe forgot to create it?"
exit 2
fi
if [ ! -e $pdf ] ; then # start latex in background, and wait later for all pids, so it takes only as long as the longest compilation takes$texbin $tex & pids[$cnt]=$! shift continue fi # do nothing, if pdf is newer then all source files if [$pdf -nt $tex ] ; then if [$pdf -nt $header ] ; then echo "$pdf is up to date."
shift
continue;
fi
fi
# now rebuild pdf as it's necessary
$texbin$tex &
pids[$cnt]=$!
shift
done

#store occured errors during pdf compilation!
errorflag=0
errorstring=

while [[ $cnt>0 ]]; do if [${pids[$cnt]} ]; then wait${pids[$cnt]} if [ 0 -ne$? ] ; then
# error occured!
logs="${names[$cnt]}.log $logs" errorflag=1 errorstring="${names[$cnt]}$errorstring"
fi;
pdf=${names[$cnt]}.pdf
$pdfcrop$pdf $pdf & fi; cnt=$(($cnt-1)); done; if [ 0 -ne$errorflag ]; then
cat $logs echo -------------------------------- echo errors occured in:$errorstring
exit 1
else
echo --------------------
echo - all pdfs created -
echo --------------------
# only exit code 0 -> no error!
exit 0
fi

-