Let's say I compile the following file with pdflatex -shell-escape test.tex
:
\documentclass{minimal}
\begin{document}
File listing is:
\immediate\write18{ls /usr}
\end{document}
This will send the output of the command ls /usr
to report/log of pdflatex
(primarily to stdout
).
There are then two cases I'd like to utilize:
- The output of
ls /usr
being included directly in the document (LaTeX stream). - The output of
ls /usr
becoming the contents of a\newcommand
(by this I mean, that I'd like the script to be executed when the\newcommand
is executed first – and upon subsequent calls to the new command, the shell code should not be executed anew).
I have read through How to execute shell script from LaTeX?, but I'm not sure if this "pipe input" can be applied to \newcommand
.
I have also read through tex – How can I save shell output to a variable in LaTeX? – and it seems that Tex' file I/O should be used; but I'm quite disliking the fact that I'd still have to redirect the script output (actually, in this case, the ls /usr
output) to a file, and then read it in, to have it as contents of a command.
So, is there an easier way to achieve what I'd want (hopefully, illustrated through an example based on the above code)?
EDIT: Ehm, I should have asked one more question earlier 🙂 I'll try with an edit here, although it will probably get missed .. 🙂
I originally asked for a \newcommand
that will execute shell code only upon its definition (i.e., in a sense it is "cached"); and the answer from @egreg does exactly that. But then – would it be possible to have a different \newcommand
definition, such that each time this newcommand is called, the shell command is executed anew? I.e. executing something like \@@input|"cat tempfile"
(which cannot be executed as such), where tempfile
changes between calls?
Best Answer
We must use
\@@input
(the primitive\input
command) because\input
in LaTeX does assignments. The setting of\endlinechar
is to avoid a spurious space in the expansion of\TeXpath
.When shell escape is active and the primitive
\input
finds a|
, it accepts as input the standard output of the following shell command.There should be a package by H. Oberdiek that does something of this kind.
Note An assignment is any TeX operation that gives a meaning or a value to a control sequence or register. During the
\edef
operation, TeX expands all commands it finds between the braces until only unexpandable tokens remain, but doesn't perform any assignment; rather, something like\catch=22
(where\catch
is the name of a count register) remains completely inaltered. Since the definition of\input
in LaTeX isthe implicit assignments performed by
\@ifnextchar
would not be performed and both\@input
and\@@input
would be expanded, which results in a complete disaster. Conversely, the\input
primitive (that LaTeX saves as\@@input
) is expandable and its expansion consists in causing TeX to read the named file. One has, of course, to be careful about what this file contains, as also this will be expanded. So other precautions have to be taken when doing this kind of operations, depending on the nature of the tokens produced by the command we want to perform and this "solution" is only a skeleton for possible "real" applications.Update 2019
After some years, things have changed and better methods are available.
For instance, with
xparse
andexpl3
the code can be improved:We could add an error message if the user doesn't pass the
-shell-escape
option for the LaTeX run.Check also
texosquery
(requires Java).