My question is closely related to LuaTeX: Split path string for use in macros. However, in contrast to this, I would like to have the basename. For example, I am interested in file from /path/to/file.ext or path/to/file.

Using Tex's \filename@parse from Extract filename from path was not possible. The command is not defined. Maybe that's because I am using LuaLaTex.

So, I tried to adapt the Lua-approach. Based on https://github.com/Donearm/scripts/blob/master/lib/basename.lua, I modified the upper code to (note the additionally escaped %):

    local name = string.gsub([[#1]], "(.*/)(.*)", "\%2")

Unfortunately, It does not output anything!?!

  • 3
    \filename@parse is defined in lualatex. – David Carlisle Apr 15 at 14:59
  • you need to use \@percentchar, \% does not expand to a % token. – David Carlisle Apr 15 at 16:04
  • I didn't get it running with \@percentchar. Anyway, I use \filename@parse now because of its potential backwards compatibility to pdflatex. I have no idea what was wrong with my first implementation. If you post it as an answer I can mark the question as answered. – Chickenmarkus Apr 16 at 7:06
  • I found out why it was not working before. I used it as \tikzsetnextfilename{\filename@parse\filename@base}. Since \tikzsetnextfilename uses \filename@parse for its own it has to be \filename@parse\tikzsetnextfilename{\filename@base} instead. – Chickenmarkus Apr 17 at 7:02

\filename@parse is defined in lualatex, the example document that you reference at

Extract filename from path

gives the same results in pdflatex or lualatex.


You can easily get the basename in LuaTeX using the FFI and a platform-dependent function. On POSIX-based systems you can use the basename() function.

Because it uses the FFI you have to enable --shell-escape.

In tex.sprint I use the first argument -2 to switch to verbatim catcodes, in case the path contains any characters which are treated special by TeX, such as {}$%#.

local ffi = assert(require("ffi"))

char *basename(char *path);

function basename(path)
    local cstr = ffi.new("char[?]", #path + 1)
    ffi.copy(cstr, path)
    return ffi.string(ffi.C.basename(cstr))
\newcommand*\basename[1]{\directlua{tex.sprint(-2, basename("\luaescapestring{\unexpanded{#1}}"))}}

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.