I'm doing this:
\documentclass{article}
\begin{document}
\write18{echo '100%' > hash.tex}
\input{hash.tex}
\end{document}
However, this doesn't work (doesn't compile). What is the workaround?
I'm doing this:
\documentclass{article}
\begin{document}
\write18{echo '100%' > hash.tex}
\input{hash.tex}
\end{document}
However, this doesn't work (doesn't compile). What is the workaround?
Since % is the comment character, you cannot use it that way. There are various solutions available.
The simplest one is to use \@percentchar, but this requires \makeatletter. Simpler is to define an alias in the preamble and use it inside \write:
\documentclass{article}
\makeatletter\let\percentchar@percentchar\makeatother
\begin{document}
\immediate\write18{echo '100\percentchar' > hash.tex}
\input{hash.tex}
\end{document}
Less obtrusive might be
\documentclass{article}
\usepackage{shellesc}
\makeatletter
\newcommand{\exec}[1]{%
\begingroup
\let%@percentchar
\ShellEscape{#1}%
\endgroup
}
\makeatother
\begin{document}
\exec{echo '100%' > hash.tex}
\input{hash.tex}
\end{document}
Why shellesc? Because \ShellEscape works with all engines, so you don't need to change code with LuaLaTeX, for instance. It does \immediate\write18 (or the equivalent), which is what you need: without \immediate, the execution would be deferred to the next page shipout and the subsequent \input would fail.
You can define \sstring macro which behaves like \string but the backslash is not printed. (Note, that LuaTeX has special primitive \cssting for such task.
\def\sstring#1{\expandafter\sstringA\string#1\relax}
\def\sstringA#1#2\relax{#2}
\write18{echo '100\sstring%' > hash.tex}
This is universal solution for all TeX-sensitive characters, for example \sstring\{, \sstring\# etc.
\@percentchar(you need\makeatletterfirst if not in package code – David Carlisle Jun 14 '20 at 11:47