Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
3  
You can say \newcommand{\foo}{\@@input|"cat tempfile"} (protect it with \makeatletter and \makeatother; each call of \foo will run the shell command. –  egreg Apr 28 '11 at 17:50
    
Awesome, @egreg - thanks so much for this comment! Cheers! –  sdaau Apr 30 '11 at 9:10
add comment

2 Answers

up vote 18 down vote accepted
\documentclass{minimal}

\begingroup\makeatletter\endlinechar=\m@ne\everyeof{\noexpand}
\edef\x{\endgroup\def\noexpand\TeXpath{\@@input|"which tex" }}\x

\begin{document}
File listing is

{\catcode`_=12 \ttfamily
\input{|"ls /usr" }

}

\TeX{} is \TeXpath
\end{document}

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 is

\@ifnextchar\bgroup\@iinput\@@input

the 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.

share|improve this answer
    
Fantastic, @egreg - thanks so much for the example! Cheers! –  sdaau Apr 27 '11 at 22:44
    
@egreg: can we do it without a temporary file? –  xport Jun 11 '11 at 6:37
    
@xport: this does not use a temporary file. –  egreg Jun 11 '11 at 9:24
    
@egreg: How to use your code above, I got an error when compiling it. I am using Windows. –  xport Jun 11 '11 at 9:26
    
@xport Did you enable the shell-escape on the command line with --enable-write18? –  egreg Jun 11 '11 at 9:40
show 3 more comments

Here is a simple way of doing this, using my bashful package

\documentclass{article}
\usepackage[a6paper]{geometry}
\usepackage{bashful}

\begin{document}
\bash[script,stdout]
ls -F /usr
\END
\end{document}

which generates Incorporating the output of <code>ls</code> into your LaTeX document

share|improve this answer
    
Awesome, many thanks for that, @Yossi Gil - cheers! –  sdaau Feb 21 '12 at 6:39
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.