17

What is the command for file copy? I want to copy the contents of one file into another without any command expansion. In a command line driven operating system one would use

copy source target

I tried reading the contents of one file into a variable and the writing it into the target:

\CatchFileDef{\OriginalF}{\jobname.sc0}{}
\newwrite\hcOutputStreamF
\immediate\openout\hcOutputStreamF=\jobname.sc1
\immediate\write\hcOutputStreamF{\OriginalF}
\immediate\closeout\hcOutputStreamF

but it expands the TeX commands saved in the original file.

1
  • 3
    While Hector knows it, for others I wanted to note that \CatchFileDef is from the ctan.org/pkg/catchfile package.
    – Stephen
    Nov 11, 2011 at 18:28

5 Answers 5

17

Here's a Plain TeX solution that uses the ε-TeX extension \readline. It copies its source to \jobname.copy.

\newread\in
\openin\in=\jobname.tex
\newwrite\out
\immediate\openout\out\jobname.copy
\endlinechar-1
\loop \unless\ifeof\in
        \readline\in to\l
        \immediate\write\out{\l}
\repeat
\immediate\closeout\out
\closein\in
\end
7

The verbatimcopy package provides the command \VerbatimCopy which seems to do exactly what you are looking for. It doesn't seem to work for "binary" (i.e., non-text) files, though.

\documentclass{scrartcl}
\pagestyle{empty}

\usepackage{verbatimcopy}
\usepackage{graphicx}

\begin{document}
  \VerbatimCopy{input.tex}{input.tmp}
  \input{input.tmp}

  % This doesn't work for binary files:
  %\VerbatimCopy{img.png}{img2.png}
  %\includegraphics{img2.png}
\end{document}

I have added a compilable example to GitHub.

6

You were very close in your original question; just replace

\immediate\write\hcOutputStreamF{\OriginalF}

with

\immediate\write\hcOutputStreamF{\unexpanded\expandafter{\OriginalF}}

and I think you'll get what you're after.

4

This one comes fairly close. The trick is to make every character non-special while copying.

\def\everythingother{%
  \count255=0
  \loop\catcode\count255=12
    \advance\count255 1
    \ifnum\count255<256 \repeat}

\newread\infile
\newwrite\outfile
\newif\ifgo

\begingroup
\obeylines
\gdef\copyfileverbatim#1#2{%
 \begingroup\everythingother
 \obeylines
 \def^^M{}
 \immediate\openin\infile=#1
  \immediate\openout\outfile=#2
  \loop
    \read\infile to\data
    \immediate\write\outfile{\data}%
    \ifeof\infile\infile\gofalse\else\gotrue\fi
    \ifgo\repeat
  \closein\infile
  \immediate\closeout\outfile
  \endgroup}
\endgroup

\copyfileverbatim{tt.in}{tt.out}
\bye

One remaining problem: any control character in the input will be copied to its TeX equivalent, so a backspace character becomes ^^H. I have no fix for that.

4
  • 10
    But honestly, I find the stated requirement somewhat bizarre. Why use TeX to copy files when every operating system does it better? Jan 17, 2011 at 17:45
  • 2
    File A was created at the beginning of the process and contains some TeX code. File A is copied to file B at the end of the TeX compilation. In the second run, I use file B to generate a "table of contents". If the compilation halted, then file B was not copied and the "table of contents" is not generated (this is what I want). If I use only one file in this work flow, then there is no way (that I know of) to prevent an incomplete file A to produce the incorrect input for the second run.
    – Hector
    Jan 17, 2011 at 17:56
  • you might be interested in the answers to tex.stackexchange.com/questions/8729/… Jan 17, 2011 at 18:21
  • 1
    @Hector: How about using a \newif\ifsuccess, and then at the end (where you would otherwise do 'copy fileA fileB') put \addtocontents{aux}{\successtrue}. You can then use \ifsuccess\input{file}\else No ToC\fi (or whatever).
    – Villemoes
    Jan 18, 2011 at 14:11
1

A solution in expl3, for future reference. The reading part is pretty much identical to How can I read the whole file content verbatim into a (expl3) string variable?.

%! TEX program = pdflatex
\documentclass{article}

\begin{filecontents*}{source.txt}
line 1  !?#\xyz
line 2
\end{filecontents*}

\ExplSyntaxOn

\ior_open:Nn \g_tmpa_ior {source.txt}
\iow_open:Nn \g_tmpa_iow {target.txt}
\ior_str_map_variable:NNn \g_tmpa_ior \l_tmpa_str {
    \iow_now:Nx \g_tmpa_iow {\l_tmpa_str}
}
\ior_close:N \g_tmpa_ior
\iow_close:N \g_tmpa_iow

\ExplSyntaxOff

\begin{document}
\end{document}

You can see the block between \ExplSyntaxOn and \ExplSyntaxOff will copy the file named source.txt to target.txt.

Note for all of the existing answers (including this one), since they use TeX primitives to read the data, trailing spaces (and possibly tabs, depends on the version) on each line will be stripped, and if the source file has no final newline it will be added. (thus binary files cannot be copied.)


An alternative includes using shell-escape. Refer to https://tex.stackexchange.com/a/585404/250119.

1
  • 1
    You could also allocate your own file streams for "code readability" -- unlike the old \newread/\newwrite, expl3 commands implement a "reference counting" system for the files to reduce the number of files used.
    – user202729
    Dec 11, 2022 at 15:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .