1

I want to output some text, verbatim, to $TMPDIR/myFile.txt, then do some other operations with that file.

Note: to allow LaTeX to write to files outside the current folder, you need to:

  • Run LaTeX with --shell-escape to allow for \input
  • Add openout_any=a to texmf.cnf to allow writing to any folder (findable in a terminal via kpsewhich texmf.cnf)

I'm trying to obtain the real file path via \input{|echo $TMPDIR/myFile.txt} as per:
https://stackoverflow.com/questions/3252957/how-to-execute-shell-script-from-latex

with complete minimal repro:

\documentclass[11pt]{article}
\usepackage{fancyvrb}

\begin{document}

\newcommand{\myFile}{\immediate\input{|echo $TMPDIR/myFile.txt}} \begin{VerbatimOut}{\myFile} my file contents here <> {} () $ "" ''. \end{VerbatimOut} % ... do something on disk with \myFile

\end{document}

However, this generates an error Bad space factor (0). on the \end{VerbatimOut} line.

Possibly related:
! Bad space factor (0)
but that answer (\leavevmode) sounds specific to seriate.

Why is this error generated, and is there a way to accomplish the above goal?

  • 2
    probably unrelated but remove \immediate from \immediate\input – David Carlisle Dec 11 '22 at 19:21
  • latex \input is not expandable so \myFile does not expand to a file name so \begin{VerbatimOut}{\myFile} can not work – David Carlisle Dec 11 '22 at 19:24
  • @DavidCarlisle how does someone determine if a particular function is expandable or not? Looking online for \input, I found various pages describing its functionality, but none mentioned its expandability.

    When something isn't expandable and is misused, it tends to cause poor errors.

    Should people just assume that everything isn't expandable, and only use expl3 definitions when expandable functions are required?

    – David Fink Dec 12 '22 at 11:46
  • Martin Scharrer's answer on the following post states "You can use \input basically everywhere with any content." and "You can nest \input macros.", which is pretty confusing, since it isn't expandable. https://tex.stackexchange.com/questions/246/when-should-i-use-input-vs-include – David Fink Dec 12 '22 at 11:52
  • 1
    it says The LaTeX version of \input only does some sanity checks and then... those checks... – David Carlisle Dec 12 '22 at 11:55

2 Answers2

2

LaTeX \input uses \@ifnextchar and is not expandable. You can use the primitive.

\documentclass[11pt]{article}
\usepackage{fancyvrb}

\begin{document} \makeatletter \newcommand{\myFile}{@@input"|echo myFile.txt" } \makeatother \begin{VerbatimOut}{\myFile} my file contents here <> {} () $ "" ''. \end{VerbatimOut} % ... do something on disk with \myFile

\end{document}

David Carlisle
  • 757,742
1

You can use \sys_get_shell:nnN of expl3:

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\getfromshell}{mO{}m} {% #1 = command, #2 = setup, #3 = control sequence \sys_get_shell:nnN { #1 } { #2 } #3 \tl_trim_spaces:N #3 }

\ExplSyntaxOff

\begin{document}

\getfromshell{kpsewhich -expand-var=$TMPDIR/myfile.txt}{\myfile}

\ExplSyntaxOn \tl_analysis_show:N \myfile \ExplSyntaxOff

\texttt{\myfile}% just to test

\end{document}

Spaces are trimmed off at either end. I'd prefer kpsewhich -expand-var so it's system independent and doesn't require shell escape.

You can pass \myfile to VerbatimOut, of course. I tested it with the call

TMPDIR=foo pdflatex davidfink

(I gave a different value to TMPDIR just not to get overlong output like /var/folders/8b/hx9v58ln1txgzv4v32_vpbr40000gq/T/) and the console shows

The token list \myfile contains the tokens:
>  f (the letter f)
>  o (the letter o)
>  o (the letter o)
>  / (the character /)
>  m (the letter m)
>  y (the letter y)
>  f (the letter f)
>  i (the letter i)
>  l (the letter l)
>  e (the letter e)
>  . (the character .)
>  t (the letter t)
>  x (the letter x)
>  t (the letter t).

Finally

enter image description here

is printed.

The full syntax is

\getfromshell{<command line>}[<setup>]<control sequence>

The <setup> argument can be used for setting category codes in case of special characters returned by the <command line>.

egreg
  • 1,121,712
  • TMPDIR is a standard environment variable and usually TeX programs are not allowed to write in the directory it points to. – egreg Dec 11 '22 at 21:26