91

What are \immediate and \write18 and how does one use them? I'd like some examples spanning from basic to advanced scenarios.

3 Answers 3

88

Both \immediate and \write are TeX primitives. The \write operation is used to write to a file stream. Like many other things in TeX, file streams are accessed by number (although usually real files are given symbolic names to make life easier). Stream 18 is 'special' as it is not a file at all: instead, it is a way of sending commands to the operating system (shell).

As TeX is a typesetting system, the standard behaviour of \write is to wait until a page is being shipped out before doing anything. That is what you want if the write operation needs things like page numbers. However, there are occasions when you want to write now, which is what \immediate forces. So

\immediate\write18{<stuff>}

means 'send <stuff> to the operating system for execution now'.

There are security issues with allowing arbitrary commands inside a TeX file, and so the standard settings in both TeX Live and MiKTeX turn off full access to \write18. You can turn it on, if you want full access, using latex --shell-escape (or similar) in place of just latex.

As to examples of use, one pretty useful one is to automatically run BibTeX at the start of each LaTeX run by including as the first line

\immediate\write18{bibtex8 --wolfgang \jobname}

The \write operation carries out expansion, and so \jobname here will be converted into the name of the current TeX file.

Recent versions of TeX Live and MiKTeX have a 'restricted \write18' concept which allows a small number of commands to work in \write18 even if --shell-escape is not given. This list is pretty short and features only 'safe' commands (where arbitrary file operations have deliberately been disabled).

10
  • 3
    @Joseph: Can we insert the output of an external application into (La)TeX document immediately without using a temporary file? Jun 11, 2011 at 7:23
  • @Joseph: For example: The external application produces some messages on a console window. Jun 11, 2011 at 7:25
  • 4
    @Joseph You might mention the "combined" action of executing a system command and getting the output into TeX by \input|"<command>" (where \input is the TeX primitive, \@@input in LaTeX).
    – egreg
    Jun 11, 2011 at 9:39
  • (How) Is it possible to write something to a file? Lets say I’d like to write the line mycmd used with #1 and #2 with each call of \mycmd{#1}{#2} to a file named mycmd.log.
    – Tobi
    Jun 12, 2011 at 9:26
  • 3
    @morbusg In texmf.cnf, for me inside /usr/local/texlive/2012/texmf/web2c/texmf.cnf (second one from kpsewhich texmf.cnf --all).
    – Joseph Wright
    Jan 17, 2013 at 11:36
41

PdfTeX has another way to execute system commands which is useful when we need to include the command's output in our document:

\input|"ls xyz.*"

will include the output of the system command enclosed in double quotes. The command line option --shell-escape (or --enable-write18 for MiKTeX) must be given, of course.

When this is used in LaTeX it's still necessary to use the primitive \input, so the construction should be

\makeatletter
\@@input|"ls xyz.*"
\makeatother

This is equivalent to the more complicated

\immediate\write18{ls xyz.* > temp.dat}
\input{temp.dat}

but doesn't require a temporary file. Unfortunately, older versions of XeTeX and LuaTeX don't know about this syntax.

7
  • 4
    Update: in TeX Live 2013 the syntax \input|"command" is supported also by XeTeX and LuaTeX.
    – egreg
    Oct 23, 2013 at 22:55
  • That doesn't work. I get the error: runpopen command not allowed: echo ! I can't find file `"|echo 42"'. l.5 \@@input|"echo 42" Apr 8, 2016 at 14:07
  • @PeterFlynn You have to run with -shell-escape, as mentioned in the answer.
    – egreg
    Apr 8, 2016 at 14:14
  • I thought I had configured LaTeX to do that in the config file, as my log output said so, but apparently that doesn't work — you do indeed have to specify --shell-escape explicitly. Weird. Apr 9, 2016 at 21:58
  • How do you escape quotes within the command? For example, how do you run ./main "foo bar"? I've tried escaping them with a backslash, but it doesn't work.
    – Anakhand
    Aug 11, 2019 at 15:39
23

The explanations of Joseph are always good. I give this answer only to show an example: elephant.ps is a picture you can find in the latex companion examples.

% with pdflatex
\documentclass[]{article}
\usepackage{graphicx}

\begin{document}
\immediate\write18{pstopdf elephant.ps}% to get elephant.pdf
\includegraphics[scale=0.5]{elephant.pdf}
\end{document} 

\immediate\write18is very useful to work with gnuplot (see gnuplottex's source), maxima, xcas and bc for examples.

4
  • 2
    The package epstopdf does that trick automatically (TeX Live 2010 is required, I don't know about MiKTeX 2.9). The commands that can be run without enabling shell-escape are repstopdf (a restricted form of epstopdf, bibtex, bibtex8, kpsewhich and makeindex.
    – egreg
    Jun 11, 2011 at 9:33
  • @egreg Yes I know but like you say, TL 2010 is required and a lot of people works with TL 2009. This is only an example and we can use other commands with shell-escape like bc. Jun 11, 2011 at 9:59
  • @egreg: I think the point here was the example, rather than necessarily saying its useful to everyone. I'd also note that you can use epstopdf quite happily with older TeX Live/MiKTeX systems, it's just that you need to enable \write18.
    – Joseph Wright
    Jun 11, 2011 at 14:13
  • @AlainMatthes Do we need to specify the full path to the file for the command to work? I am having trouble with pdfcrop. I am running the command: \immediate\write18{pdfcrop file.pdf} at the end of my document but I get no output. Jun 29, 2016 at 2:02

You must log in to answer this question.

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