# How can I open a file in “append” mode?

Could not find anything in the TeXBook, but this could be just me.

I guess it is always possible to open the file for reading, copy its content to another file, and then continue writing to that file. Finally, you could escape to shell to remove the original file and rename the newly generated file to the file you have just created.

-
I've wondered about this, and concluded that the only way is as you say to read everything in. The TeX \openout primitive simply does not allow appending. (Of course, LuaTeX is a different case). –  Joseph Wright Feb 23 '11 at 7:37
@Joseph: if you write this as an answer, I could mark it is as correct, just to tidy this up and close that question. –  Yossi Gil Feb 24 '11 at 0:08
Related question: "File copy without expansion" –  Martin Scharrer Mar 1 '11 at 17:00

I agree with Joseph that TeX doesn't support appending to an existing file. However it is possible to read the existing content and write it together with the new content back to the file. This is of course much less efficient than simply appending content, but the only possible way in TeX.

The catchfile makes the reading of the existing content quite easy:

\documentclass{article}

\usepackage{catchfile}

\newwrite\appendwrite
\newcommand*\appendtofile[2]{%
\begingroup
\IfFileExists{#1}%
{\CatchFileDef{\filecontent}{#1}{\endlinechar=^^J\catcode\endlinechar=12\relax}}% keep existing end-of-lines
{\let\filecontent\empty}%
\immediate\openout\appendwrite=#1\relax
\immediate\write\appendwrite{\filecontent #2}%
\immediate\closeout\appendwrite
\endgroup
}

\begin{document}

\appendtofile{\jobname.test}{First line}

First:\\\fbox{\input{\jobname.test}}

\appendtofile{\jobname.test}{Second line}

Second:\\\fbox{\input{\jobname.test}}

\end{document}


-

I've wondered about this, and concluded that the only way is as you say to read everything in. The TeX \openout primitive simply does not allow appending. (Of course, LuaTeX is a different case). If you are going to read everything in, the e-TeX \readline primitive might be useful, as it reads everything detokenized.

-

You could write what you want to append into a new file, and rewrite both files together at the end of the run. Something like the following.

\documentclass{minimal}
\newwrite\mywrite
\newcount\mycount

\makeatletter
\newcommand{\makeallother}{%
\mycount0\relax
\loop\ifnum\mycount<255\relax
\catcode\mycount12\relax
\repeat
}
\newcommand*{\VerbatimFile}[2]{%
\begingroup
\newlinechar\endlinechar
\makeallother
\everyeof{\noexpand}%
\immediate\openout\mywrite #1\relax
\def\from##1{\immediate\write\mywrite{\@@input ##1 }}%
#2\relax
\immediate\closeout\mywrite
\endgroup
}
\makeatother

\AtBeginDocument{\immediate\openout\mywrite\jobname.append\relax}
\AtEndDocument{%
\immediate\closeout\mywrite
\VerbatimFile{\jobname.output}{%
\from{\jobname.tex}%
\from{\jobname.append}%
}%
}

\begin{document}

\newcommand{\test}[1]{\immediate\write\mywrite{#1}}
\test{abc}
\test{cde}

\end{document}
`
-