22

What's the Lua to get the current working directory on Windows XP SP3 (or to get the directory of the currently-running Lua file)? I prefer not to use LuaFileSystem.

I can't use os.execute("cd") because os.execute always starts from my home directory (and thus always yields C:\Documents and Settings\username).

6 Answers6

20

maybe some ugly hack like

current_dir=io.popen"cd":read'*l'
jpjacobs
  • 9,359
  • 36
  • 45
  • This seems to have the same effect as `os.execute("cd")`. –  May 18 '11 at 14:26
  • 3
    nope, os.execute'cd' only prints the output, while the io.popen thing captures it, and puts it in the current_dir variable – jpjacobs May 19 '11 at 11:26
  • Have to close the "popen" - maybe store the popen in a local and close it after the read. Otherwise this will leak handles. – Arun R Aug 06 '13 at 19:40
  • 1
    @ArunR It will only "leak" handles temporarily until they're garbage collected. Try `print(io.popen("ls").__gc)`. – Craig Barnes Dec 29 '14 at 18:48
  • does not work for me on macOS with lua 5.4, it returns `nil`. – jdhao Oct 20 '22 at 19:29
13

Lua by default doesn't have a "native" way of supporting the concept of "current directory", or, in fact, the concept of "directory".

The proper way to get the current directory is using a library that provides folder support. There are several - I recommend luafilesystem.

Once it is installed, you can get the current directory by executing:

lfs.currentdir()

This will work on windows, linux and mac.

Beware though that these external libraries usually involve some binary packages. Depending on your setup, you might have to compile it before being able to use it.

EDIT:

Note that when a file is included via require, then the expression {...}[1] returns the path used by the require directive. It is not exactly the path because:

  • It uses dots to separate directories and supresses the .lua at the end of the file.
  • It is relative to the path from which the lua process was initialized
  • It depends on the configuration of package.path

But if all you need is the "require-like path" of the file (maybe to require files next to it) then you can get it by doing this at the very beginning of the file:

local PATH = (...):match("(.+)%.[^%.]+$") or (...)

If a file called baz.lua is required with require 'foo.bar.baz', then PATH will be foo.bar.

Faheem Mitha
  • 6,096
  • 7
  • 48
  • 83
kikito
  • 51,734
  • 32
  • 149
  • 189
9

You should be able to get the currently-running lua file path with:

debug.getinfo(1).short_src;

or

debug.getinfo(1).source;

and then the current directory with a regex:

string.gsub(debug.getinfo(1).short_src, "^(.+\\)[^\\]+$", "%1");

Edit: actually that only works if you're running your lua with the full path. e.g.: "lua.exe C:\test\test.lua" and NOT "lua.exe test.lua"

aryu
  • 99
  • 2
  • 3
  • 3
    In Linux I had to use `debug.getinfo(1).source` and change the regex to `string.gsub(debug.getinfo(1).source, "^@(.+/)[^/]+$", "%1")`. – Gus E Jul 09 '14 at 14:07
  • For a lua newbie playing around with neovim config files, your answer is a saver! Thank you @GusE – Gru Jul 29 '22 at 04:25
5

I haven't had time to test this, but have you tried os.getenv to read windows environment variables?

Windows has an environment variable for current directory: %CD%

os.getenv("CD")

Edit: Tested on Windows 7 and while other environment variables work (ie. %USERNAME% or %PROGRAMFILES%) the CD var returns nil

Adam
  • 3,053
  • 2
  • 26
  • 29
  • Yeah, I had tried getenv without any luck. I'm starting to think it's not possible without LuaFileSystem. –  May 17 '11 at 20:26
  • I was able to pass the %CD% variable to the script, might work depending on how you execute your scripts. I.E: C:\>lua5.1.exe test.lua %CD% (then the path is available as arg[1]) – Adam May 17 '11 at 20:46
  • 3
    %CD% is not a process environment variable, it's provided by the shell, so it won't work – CharlesB May 17 '11 at 20:59
  • 1
    try `os.getenv("PWD")` on mac – Robert Ranjan Sep 22 '21 at 00:59
1

I tried all these answers but nothing worked. I tested the following script, and it works as expected.

io.popen("cd"):read()
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Pawan Kumar
  • 114
  • 9
0

You could use alien to call out to GetCurrentDirectory in kernel32.dll, but that's probably not what you're looking for.

Stuart P. Bentley
  • 10,195
  • 10
  • 55
  • 84