What are \immediate and \write18 and how does one use them? I'd like some examples spanning from basic to advanced scenarios.
- 250,273
- 46,933
3 Answers
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).
- 259,911
- 34
- 706
- 1,036
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.
- 707
- 1,121,712
-
4Update: in TeX Live 2013 the syntax
\input|"command"is supported also by XeTeX and LuaTeX. – egreg Oct 23 '13 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"
– Peter Flynn Apr 08 '16 at 14:07 -
@PeterFlynn You have to run with
-shell-escape, as mentioned in the answer. – egreg Apr 08 '16 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. – Peter Flynn Apr 09 '16 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 '19 at 15:39 -
-
@egreg I tried that, but it seems single quotes don't work on Windows or with Python's
argparse– Anakhand Aug 11 '19 at 16:07
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.
- 95,075
-
2The 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 ofepstopdf,bibtex,bibtex8,kpsewhichandmakeindex. – egreg Jun 11 '11 at 09: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. – Alain Matthes Jun 11 '11 at 09: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
epstopdfquite happily with older TeX Live/MiKTeX systems, it's just that you need to enable\write18. – Joseph Wright Jun 11 '11 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. – codeaviator Jun 29 '16 at 02:02
\input|"<command>"(where\inputis the TeX primitive,\@@inputin LaTeX). – egreg Jun 11 '11 at 09:39mycmd used with #1 and #2with each call of\mycmd{#1}{#2}to a file namedmycmd.log. – Tobi Jun 12 '11 at 09:26\write, not\write18(which as I said is for O/S operations). 'Normal' file writing would be a separate question: please ask one! (Here on tex.sx, the idea is that each answer should broadly stick to the question in hand, and each question should ideally focus on one issue.) – Joseph Wright Jun 12 '11 at 14:09--shell-escapeand-shell-escape? – kiss my armpit Dec 31 '12 at 19:38-for 'long name' options, with one-for 'short' ones (normally one letter). In the case of the binaries in TeX Live, both one and two-seem to be accepted for option names. – Joseph Wright Dec 31 '12 at 19:41texmf.cnf, for me inside/usr/local/texlive/2012/texmf/web2c/texmf.cnf(second one fromkpsewhich texmf.cnf --all). – Joseph Wright Jan 17 '13 at 11:36