0

I need to include a large number of files in my ConTeXt document:

\starttext

    \include file1
    \include file2
    \include file3
    \include file4
    \include file5

\stoptext

They are all generated by a script, so I don't know how many files there are beforehand are, but they must be included in alpha-numerical order, not randomly.

I found this Including all files within a directory, How to iterate through the name of files in a folder, and many other LaTeX solutions, but cannot find a solution in ConTeXt, and found nothing in the manuals.

How can I include all of the files found in a folder?

Village
  • 13,603
  • 23
  • 116
  • 219
  • Have you tried making a call from Lua? It should be straightforward… – TeXnician May 01 '19 at 12:26
  • It might be easier if the script generating the file-names were rewritten so as to output names in the style file 001, file002 … file999. That way, you don't have to worry about the difference between a lexical sort (10 before 9) and a numerical sort (09 before 10). On the other hand, if someone thinks of a solution using ConTeXt's \dorecurse or \dostepwiserecurse you would be OK without the zero-padding. The most relevant wiki pages seem to be this one and this one. –  May 01 '19 at 18:17

2 Answers2

3

Instead of using the shell and all sorts of platform-dependent tools, you can use the builtin Lua Filesystem library of LuaTeX to traverse all files in the current directory. When iterating I test whether the element has the .tex extension and that it actually is a file and then append it to the list of files. The list is then sorted inplace using a lexical sort by table.sort. In the document we can then loop over list of files and call context.input for each of them.

\startluacode
local files = {}

for file in lfs.dir(lfs.currentdir()) do
    if file:match("%.tex$") and lfs.attributes(file, "mode") == "file" then
        files[#files + 1] = file
    end
end

table.sort(files)
\stopluacode

\starttext

\startluacode
for _, file in ipairs(files) do
    context.input(file)
end
\stopluacode

\stoptext
Henri Menke
  • 109,596
  • Does this work if the file before file10.tex is called file9.tex, or does it have to be called file09.tex? –  May 01 '19 at 22:13
  • @TEV Of course it works, but I presume you are asking about the ordering. As stated in my answer, table.sort performs lexical ordering, i.e. file10.tex will appear before file9.tex. But you can provide your own comparison function as a second argument to table.sort. – Henri Menke May 01 '19 at 22:15
1

Minimal working example with names exactly as specified by you:

\starttext
\directlua 0 { os.execute("ls | sed -n '/^file[0-9][0-9]*$/s/^file//p' | sort -n | sed 's/.*/\\\\input file&/' > ListOfFiles.tmp") }

\input{ListOfFiles.tmp}
\stoptext

I'm not saying this is a good example, just a working example. Yes, it really does use a quadruple backslash to get a single backslash into the temporary file. The embedded sed scripts become only slightly more complicated if your files have names like file1.txt, file2.txt. Something like this:

\starttext
\directlua 0 { os.execute("ls | sed -n 's/^file\\([0-9][0-9]*\\)\\.txt$/\\1/p' | sort -n | sed 's/.*/\\\\input file&.txt/' > ListOfFiles.tmp") }

\input{ListOfFiles.tmp}
\stoptext

If you're using Windows, I guess you would have to run ConTeXt from something like Cygwin or Msys to make this monstrosity work. Or rewrite it it pure lua that doesn't use sh, ls, sed & sort.