Why can't filecontents work in a macro

There are various reasons why it fails.

First and most important reason: when tokens are absorbed as the argument to another command, including \newcommand and \AtEndDocument, they receive their category code (if not control sequences) and endlines are converted to spaces or \par tokens.

When \begin{filecontents} is being processed, several changes are made, which are quite similar to what happens for verbatim (not completely the same); for instance you don't want that the backslash maintains its usual meaning, nor you want that an endline is converted to a space.

For this reason, the closing \end{filecontents} which TeX looks for is not 15 tokens

\end • { f • i • l • e • c • o • n • t • e • n • t • s • }

but 18:

\ • e • n • d • { f • i • l • e • c • o • n • t • e • n • t • s • }

where the backslash and the braces have category code 12; actually the lookup also includes the endline (which must be an active character, with a very particular meaning).

There are several other issues, particularly in connection with non ASCII characters.

Can this be corrected? Not in full generality.

Chances are that you don't really need filecontents, because writing a file, with a given content, at the beginning or at the end of processing should not make any difference. So probably you're looking at the wrong tool for what you have in mind.


You're better off creating an output stream that you append stuff to; newfile provides this functionality:

\documentclass{article}
\usepackage{filecontents,newfile}

\begin{filecontents*}{\jobname.abc}
this gets in the file \jobname.abc
\end{filecontents*}

\newoutputstream{mystream}
\openoutputfile{\jobname.def}{mystream}
\newcommand{\toto}{%
  \addtostream{mystream}{this will be written to \jobname.def.}%
}

\begin{document}

Some text. \toto

\end{document}

The written files - \jobname.abc and \jobname.def - contain the following:

  • latex_stuff.abc

    this gets in the file latex_stuff.abc.

  • latex_stuff.def

    this will be written to latex_stuff.def.

Tags:

Filecontents