[Tex/LaTex] How to write % into a file

auxiliary-filesverbatimwrite file

How can I write % into an auxiliary file? % will not work, because LaTeX thinks that I start a comment with it (in the main file, not in the auxiliary file!), and \% will write \% into the file. How can it be accomplished?

\documentclass{article}
\begin{document}
\newwrite\outfile
\immediate\openout\outfile=example.dat
\immediate\write\outfile{%}% will not work, of course, but neither \%
\immediate\closeout\outfile
\end{document}

Best Answer

There is \@percentchar that expands to a literal % character. You need to enclose your writing operation in a \makeatletter \makeatother pair

\makeatletter
\newwrite\outfile
\immediate\openout\outfile=example.dat
\immediate\write\outfile{\@percentchar}
\immediate\closeout\outfile
\makeatother

An alternative with escaping the % inspired by an example where

git log -1 --pretty=format:"%h-%ad" --date=short > /tmp/temp.dat

needs to be passed to \write18

\makeatletter
\newcommand\dosystem{%
  \@ifstar{\@tempswafalse\do@system}{\@tempswatrue\do@system}%
}
\newcommand\do@system[1]{%
  \begingroup
  \let\%\@percentchar
  \if@tempswa\expandafter\immediate\fi
  \write18{#1}%
  \endgroup
}
\makeatother

so the command above can be executed by saying

\dosystem{git log -1 --pretty=format:"\%h-\%ad" --date=short > /tmp/temp.dat }

With \dosystem* the \write is delayed at the next shipout (because \immediate is not executed).

Other characters can be escaped using the same idea, adding other \let instructions. If also braces and # are needed, an extended definition would be

\makeatletter
\newcommand\dosystem{%
  \@ifstar{\@tempswafalse\do@system}{\@tempswatrue\do@system}%
}
\edef\@hashmark{\string#}\edef\@lbrace{\string{}\edef\@rbrace{\string}}
\newcommand\do@system[1]{%
  \begingroup
  \let\%\@percentchar
  \let\#\@hashmark
  \let\{\@lbrace
  \let\}\@rbrace
  \if@tempswa\expandafter\immediate\fi
  \write18{#1}%
  \endgroup
}
\makeatother

and in the argument also \#, \{ and \} can be used for escaping those characters.