I am trying to compile a document where a section is made up of various subsections (one for each topic I want to report), each of them made up of a different number of subsubsections (varying depending on the topic).

As the number of topics, as well as the number of subsections is likely to change in future, I need to automatize the process.

Ideally, what I need to achieve is like


foreach \section in {a,b,c}{
   foreach \subsection in {1,2,3}{

Where file is a composite name made by \subsection\textunderscore\section.tex

I found several suggestions. The one I think best suits my need is this \ForEach fails with underscores. However, I could not find a way to access the outer loop item to include the levelitem into the name within the inner loop, the one defining the first part of the name of the file I want to input.

I am relatively new to loops in latex (and also to latex, to a certain extent) so I am surely missing something.

I have only been able to make the first loop working. The solution might lie in the \ForEachSublevel command, but even reading the forarray manual, I have not been able to come up with a solution.

Below, my code


% Packages

% ----------------------------
% https://tex.stackexchange.com/questions/456693/foreach-fails-with-underscores



% -----------------------------
% ------------------------------------------


% https://tex.stackexchange.com/questions/456693/foreach-fails-with-underscores
      {% Open local scope
      \subsection{SYNTH OUTCOME ON \thislevelitem \hspace{1pt} OUTCOME}%

      }% Ends local scope
}% ForEach ends here
ipc\myunderscore ruleoflaw,ipc\myunderscore politicalrights,ipc\myunderscore gender,ipc\myunderscore socprotection,ipc\myunderscore business,ipc\myunderscore health,ipc\myunderscore work,ipc\myunderscore edu,ipc\myunderscore security,ipc\myunderscore environment,ipc\myunderscore minority,ipc\myunderscore cvrights,ipc\myunderscore womenrights,ipc\myunderscore corrupt% Needed comment

Welcome to TeX.SE! I believe you want something like this:


\cs_new_eq:NN \clistmapinline \clist_map_inline:nn


  \clistmapinline{a, b, c}{%
    \section{Section #1}%
    \clistmapinline{1, 2, 3}{%
      \subsection{Subsection ##1}%


This reads the following files: 1_a.tex, 2_a.tex, 3_a.tex, 1_b.tex, 2_b.tex, 3_b.tex, 1_c.tex, 2_c.tex, and 3_c.tex.

\clistmapinline replaces #1 with the thing being iterated on, and ## with a single #. Therefore, when the outer loop has been unrolled, all occurrences of ##1 in the inner loop code have become #1. This is why the inner code has access to its current item with ##1 and to the outer current item with #1.

\textunderscore is for typesetting. For an underscore that is part of the name of a file to input, you need a plain underscore.

Here is the output with obvious dummy contents in each input file.


| improve this answer | |
  • thank you very much. Your solution worked! – Filippo Santi Jan 20 at 16:13

Here's the directory listing:


I abbreviated the list of files to two, for simplicity. The mock files just contain the file name without ipc and underscores.




  \santi_cycle:nn { #1 } { #2 }

\int_new:N \g__santi_cycle_int
\cs_generate_variant:Nn \clist_map_function:nN { nc }

\cs_new_protected:Nn \santi_cycle:nn
  \int_gincr:N \g__santi_cycle_int
  \cs_set:cn { \__santi_cycle_name: } { #2 }
  \clist_map_function:nc { #1 } { \__santi_cycle_name: }
  \int_gdecr:N \g__santi_cycle_int
\cs_new:Nn \__santi_cycle_name:
  __santi_cycle_\int_to_roman:n { \g__santi_cycle_int } :n


    \subsection{SYNTH OUTCOME ON ##1 OUTCOME}


The assumption is that you have files named


Adapt to your needs.

The \cycle macro loops over the list given as first argument, executing what's specified in the second argument, where #1 stands for the current item. This code can contain another \cycle, but its second argument must refer to the current item of the inner cycle with ##1 (using #1 is allowed to refer to the current item of the outer cycle).

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.