Concatenate a variable with a string in a loop

errorsfor loopvariable

I want to use subfile within a loop to add new pages to a document, depending on the number of lines in a .txt file.
The .txt may look like this:

0001
0002
0003

The .tex Subfiles are A0001.tex, A0002.tex A0003.tex

My code:

\documentclass{article}
\usepackage{subfiles}
\usepackage{forloop}

\begin{document}%
%
\newread\file%
    \openin\file=mytextfile.txt%
        \loop\unless\ifeof\file%
            \read\file to\linecontent%
            \subfile{A\linecontent}
            \newpage%
        \repeat%
    \closein\file%
\end{document}

I get this error messages for codeline 22 (\repeat), despite that the .pdf is created and looks correct.

Paragraph ended before @iinput was complete.

Extra }, or forgotten \endgroup. @import …er #1\expandafter
{\import@path@file }

If i change the subfile input to only one subfile (A0001), there is no error but it adds 4 ! new pages as if there where 4 lines in the .txt file.

\subfile{A0001}

I think im missing some small detail, but i really dont know what.

Best Answer

The main problem is that the contents of \linecontent ends with a space that should be trimmed off.

Here's a simpler implementation with a predefined expl3 loop (avoid reinventing the wheel):

\documentclass{article}
\usepackage{subfiles}

\ExplSyntaxOn

\NewDocumentCommand{\batchsubfiles}{m +O{}}
 {% #1 = file name, #2 = code to execute after each \subfile command
  \patrix_batchsubfiles:nn { #1 } { #2 }
 }

\ior_new:N \g_patrix_batchsubfiles_ior

\cs_new_protected:Nn \patrix_batchsubfiles:nn
 {
  \ior_open:Nn \g_patrix_batchsubfiles_ior { #1 }
  \ior_map_inline:Nn \g_patrix_batchsubfiles_ior
   {
    \subfile{A##1}
    #2
   }
 }

\ExplSyntaxOff

\begin{document}

\textbf{Nothing in between}

\batchsubfiles{subfiles.txt}

\bigskip

\textbf{With paragraph break after subfiles}

\batchsubfiles{subfiles.txt}[\par]

\end{document}

The subfiles.txt file is

0001
0002
0003

and the subfiles contain what's evident from the output below.

enter image description here

Some explanations

  1. \ior_new:N \g_patrix_batchsubfiles_ior is the analog of \newread\file

  2. \ior_open:N \g_patrix_batchsubfiles_ior { filename } is the analog of \openin\file=filename; here the file name is passed as the mandatory argument to \batchsubfiles, via the internal function \patrix_batchsubfiles:nn

  3. \ior_map_inline:Nn is the analog of the \loop construction you use, with several advantages over it:

    • one doesn't need to test for \ifeof
    • the implicit empty line at the end of the file is automatically ignored
    • there is no need to use a control sequence to store the contents of the current line, one just uses #1 instead; here ##1 because we're inside a definition
    • the implicit space at the end of lines is automatically ignored
  4. the mapping is done on one line at the time

  5. one can also do a test in the body of the loop and break it, if some condition is satisfied; for instance one could test for an empty line and break if found with

    \tl_if_empty:nT { ##1 } { \ior_map_break: }
    
Related Question