# Shell escape after PDF is finished and closed?

I like to escape to the shell using \write18 at the very end of the compilation after the PDF file got completely written and was closed, so that I can use it as part the shell command. Is this somehow possible or does TeX simply closed the PDF at the very last thing? Placing it direct before \end{document} or in \AtEndDocument doesn't help (unsurprisingly). AFAIK \writes are actually whatsit objects and would be normally be part of the document. So I don't have much hopes.

### Background

This is used for automatic PDF-to-PNG conversion as a new feature of standalone. At the moment I do this in the preamble in the second run when the old PDF did not yet got opened. This works fine, but I would like to avoid the need to compile standalone diagrams twice.

-
Is there a way to write18 in the preamble a shell command that "waits until compilation ends and then does something"? That would be a way around it? –  Seamus Jul 13 '11 at 15:30
@Seamus: Nice idea. I will look into it. However this might be platform dependent :-( –  Martin Scharrer Jul 13 '11 at 15:39
almost certainly, but all the cool kids use unix, so I wouldn't worry about windows compatibility... –  Seamus Jul 13 '11 at 15:43
@Seamus: I will cite you in the package manual then :-) –  Martin Scharrer Jul 13 '11 at 15:47
@Seamus: I think I need the process ID of the LaTeX compiler. It's however not the parent ID which is the shell which got started... –  Martin Scharrer Jul 13 '11 at 19:02

You do something like this (based on an idea of Ulrich Diez):

\documentclass{article}

\ifx\conditionmacro\undefined
\immediate\write18{%
pdfLaTeX --jobname="\jobname"
\gdef\string\conditionmacro{1}\string\input\space\jobname
}%
\immediate\write18{%
LaTeX --jobname="\jobname"
\gdef\string\conditionmacro{1}\string\input\space\jobname
}%
\immediate\write18{dvips \jobname}
\expandafter\stop
\fi

\begin{document}
abc
\end{document}


I'm not quite sure if it a very good idea to use \jobname in the subprocesses, it seems to work but \jobname1 or something like this is perhaps safer.

Btw: I'm one of uncool kids who uses windows.

-
Ok, basically I already use the first part of it, just the \stop here is new. Thanks, I didn't know it before. Running the same compiler internally and then the conversion script, then stop the main process before it touches the PDF. This should work. One drawback is that you need full shell escape. The conversion script alone would only required restricted shell escape and its name added to the list. This is my config, but the normal usage will be using full shell escape anyway. –  Martin Scharrer Jul 13 '11 at 18:51
Is there a way to figure out the compiler which got used? I used \ifpdf pdf\fi latex so far. –  Martin Scharrer Jul 13 '11 at 19:49
I'm not sure I would be happy if some package allowed itself to do such things in my document :-) –  Andrey Vihrov Jul 14 '11 at 7:45
@Martin: ctan.org/pkg/iftex –  Andrey Vihrov Jul 14 '11 at 7:46
@Andrey: It's not a package but a class which does this only if the user request it to do so. –  Martin Scharrer Jul 14 '11 at 7:48

I don't think it's possible; the only place where to hook is \end; let's see an example in LaTeX:

\makeatletter
\let\@@@@end\@@end
\def\@@end{\immediate\write18{ls -l \jobname.pdf}\@@@@end}
\makeatother

\documentclass{article}
\begin{document}
abc
\end{document}


Compiling it gives on standard output

-rw-r--r--  1 staff  159 Jul 13 17:50 shellatend.pdf

but ls -l shellatend.pdf after compilation has ended gives

-rw-r--r--  1 staff  10200 Jul 13 17:50 shellatend.pdf

So the PDF file has not yet been written out completely.

Putting the shell command after \@@@@end does nothing (obviously).

-
That's what I thought. I just hoped that there was some thing or dirty trick which allowed that and I simply didn't now yet. –  Martin Scharrer Jul 13 '11 at 18:46

A non-portable solution, which appears to work with TeXLive 2011's pdflatex --shell-escape run in the sh shell (hence most likely any shell based on sh) is to detach the process that you want to run after the end of the pdflatex run. To ensure that things happen after the run has really ended, I used

sleep 3&&\
nohup cp \jobname.pdf \jobname.copy\
2>/dev/null


(without the newline continuations). The first instruction waits 3 seconds for the end of the run (that number is arbitrary), with && detaching it (not sure how that works exactly). Then cp \jobname.pdf \jobname.copy copied the result pdf file; you could replace by the convert utility, or any other actual conversion program. I'm not quite sure why nohup is needed for that but not for the sleep command, but that prevents the call to cp to abort when the parent process (pdflatex) ends. The final step is to redirect errors to 2>/dev/null, because for some reason nohup produces an error (that's probably a bad sign, to investigate).

Of course, to use this in a package for general consumption, you'd need to figure out similar solutions for Windows and Mac, I guess, and figure out whether this covers all other OSes.

\documentclass{article}
\usepackage{lipsum}
\begin{document}

\section{Foo}
\lipsum[1-10]

\section{Bar}
\lipsum[11-20]

\immediate\write18{ls -la \jobname.*}
\immediate\write18
{sleep 3&&nohup cp "\jobname.pdf" "\jobname.copy" 2>/dev/null&}
\end{document}

-
I get the message appending output to nohup.out which is not an error: since the process is detached from the terminal there must be an output channel different from the terminal. If you say 1>/dev/null you get neither the message nor the nohup.out file. But, of course, this depends on what commands are needed. It work on Mac OS X, by the way. –  egreg Jan 19 '12 at 7:45
@egreg I suppose the easiest is to redirect both 1 and 2. Not sure why that's different between sh and your shell. –  Bruno Le Floch Jan 19 '12 at 20:06