(Edit: How to do file system operations and binary execution with LuaTeX in an OS-independent manner? I had written a set of macros for pdfTeX to do this using the \write18 command. These macros were meant to be usable under both Windows and Linux, giving some "higher level" control. Now I wanted the macros to also support LuaTeX. My first experiments were unsuccessful, however. Trying to reduce the problem by omitting all macros and executing LuaTeX on the command line mislead the focus to an unimportant problem before I found a solution some days later.)

In a minimal testing environment (see Minimal Testing Environment For LuaMetaTeX) I can do the initial memory dump

    luatex --ini ./plain.tex \dump

and then I would expect the following command to list the directory:

    luatex --fmt=./plain.fmt --shell-escape \directlua {os.execute ("dir")}\end

but it just tells me:

    This is LuaTeX, Version 1.13.2 (TeX Live 2021/W32TeX)
     system commands enabled.
    No pages of output.
    Transcript written on texput.log.

So how do I execute system commands under LuaTeX as it is possible under pdfTeX with \write18?

  • 1
    using luatex from texlive luatex --shell-escape '\directlua {os.execute ("dir")}\end' lists all the files in the directory for me (I need the single quotes to protect the \ from the commandline shell) Jan 8, 2022 at 8:32
  • Thank you for testing, @David! Now, your very example gives me a fatal error message: ! I can't find file `''. whereas it does indeed work for me having exchanged double and single quotes: luatex --fmt=./plain.fmt --shell-escape "\directlua {os.execute ('dir')}\end". That's fine, yet it looks as if LuaTeX's behavior were a bit unpredictable across installations.
    – Gerolf
    Jan 8, 2022 at 18:14
  • Similarly, quoting the primitive in luatex --ini ./plain.tex "\dump" works whereas luatex --ini ./plain.tex '\dump' produces a 1 page, 180 bytes plain.dvi output. luatex --help doesn't mention as syntax-conforming any quoting of remaining commands to be processed by LuaTeX.
    – Gerolf
    Jan 8, 2022 at 18:19
  • 5
    that quoting is not under the control of luatex, that is the syntax of whatever shell you use in the command line, windows shell and different unix shells have different rules for double and single quotes and backslashes Jan 8, 2022 at 19:49
  • I think it would be a good idea to match the question to the answer, i.e., ask how you can write code for a cross-platform shell-escape aware check of a few things and then leave the answer as it is. Voting to close for now, it can be reopened after an edit.
    – Marijn
    Jul 9, 2022 at 10:59

1 Answer 1


I over-minimized this test by entering a LuaTeX command at the shell prompt without the necessary quoting, as @David explained, so I did not get the expected output. Within a document, the same command must not be quoted, and the problem shifts to getting the output from the system into a command sequence. The idea is being able to run under both unix and windows while failing gracefully under pdfTeX or if --shell-escape is not set.

    \def \system #1#2#3{{%
      % #1: unix command, #2: windows command, #3: control sequence (return value) 
      \xdef #3{}%
      \ifx \directlua \undefined
        \message {! No \string\directlua\space support (LuaTeX required).}%
        \edef \escapestate {\directlua {tex.write (status.shell_escape)}}%
        \def \one {1}%
        \ifx \escapestate \one
          \edef \ostype {\directlua {tex.print (os.type)}}%
          \def \unix {unix}% os.type can be "unix", "windows", or "msdos"
          \directlua {% 
            \ifx \ostype \unix
              local file = io.popen ([[#1]]);
              os.execute ([[#1]]);
              local file = io.popen ([[#2]]);
              os.execute ([[#2]]);
            local content = file:read "*a";
            file:close ();        
            tex.toks [5] = content; }%
          \xdef #3{\the \toks 5}%
        \else \message {! No --shell-escape switch set for system command.}\fi
      \fi }}  

    \bgroup \newlinechar = 10     
      \system {setterm --clear}{cls}\myresult  
      \system {time}{time /t}\myresult
        \message {^^JSystem time:^^J\myresult}   
      \system {cd}{cd}\myresult
        \message {^^JCurrent folder:^^J\myresult}  
      \system {ls -l}{dir /b}\myresult
        \message {^^JFiles in current folder:^^J\myresult}  
      \system {set}{set}\myresult
        \message {^^JEnvironment variables:^^J\myresult}  
    \egroup \end

Save above file as curdir.tex and run:

    luatex --fmt=plain --output-format=pdf --shell-escape ./curdir.tex \end
  • 2
    I don't see how this answers your question. Jan 15, 2022 at 10:26
  • @José: Hope I could fix the issues.
    – Gerolf
    Jan 26, 2022 at 23:27

You must log in to answer this question.

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