获取包含lua文件的路径

时间:2011-06-17 02:39:58

标签: filesystems lua

我想知道是否有办法获取当前正在执行的lua脚本文件的路径?

这特别不是当前的工作目录,可能完全不同。我知道luafilesystem会让我获取当前的工作目录,但它似乎无法告诉当前正在执行的脚本文件。

由于

编辑: 我没有从标准命令行解释器运行,我正在通过luabind从C ++二进制文件执行脚本。

10 个答案:

答案 0 :(得分:15)

这是一种更优雅的方式:

function script_path()
   local str = debug.getinfo(2, "S").source:sub(2)
   return str:match("(.*/)")
end

print(script_path())

答案 1 :(得分:6)

如果标准命令行解释器正在运行Lua脚本,请尝试arg[0]

答案 2 :(得分:3)

正如lhf所说:

~ e$ echo "print(arg[0])" > test.lua
~ e$ lua test.lua
test.lua
~ e$ cd /
/ e$ lua ~/test.lua
/Users/e/test.lua
/ e$ 

这是使用debug.getinfo机制的相同信息

~ e$ echo "function foo () print(debug.getinfo(1).source) end; foo()" > test.lua
~ e$ lua test.lua
@test.lua
~ e$ cd /
/ e$ lua ~/test.lua
@/Users/e/test.lua
/ e$ 

可从C API lua_getinfo

获取

答案 3 :(得分:3)

获得所需内容的唯一可靠方法是将dofile替换为您自己的此函数版本。即使debug.getinfo方法也不起作用,因为它只会返回传递给dofile的字符串。如果那是一条相对路径,它就不知道它是如何转换为绝对路径的。

重写代码看起来像这样:

local function CreateDoFile()
    local orgDoFile = dofile;

    return function(filename)
        if(filename) then --can be called with nil.
            local pathToFile = extractFilePath(filename);
            if(isRelativePath(pathToFile)) then
                pathToFile = currentDir() .. "/" .. pathToFile;
            end

            --Store the path in a global, overwriting the previous value.
            path = pathToFile; 
        end
        return orgDoFile(filename); --proper tail call.
    end
end

dofile = CreateDoFile(); //Override the old.

函数extractFilePathisRelativePathcurrentDir不是Lua函数;你必须自己写。 extractFilePath函数从文件名中提取路径字符串。 isRelativePath获取路径并返回给定路径是否为相对路径名。 currentDir只返回当前目录。此外,您需要在Windows计算机上使用“\”而不是“/”。

此函数将路径存储在名为path的全局中。您可以将其更改为您喜欢的任何内容。

答案 4 :(得分:2)

我找到的最短形式如下:

debug.getinfo(1).source:match("@?(.*/)")

索引1,2-其他 - 取决于您要查询的调用堆栈中的哪个函数。 1是最后一个叫做函数(你在哪里)。如果你在全球范围内运行,那么可能2更合适(没有自己测试)

答案 5 :(得分:0)

查看Lua调试库,它是标准Lua发行版的一部分。您可以使用debug.getinfo查找当前文件,或调用堆栈上的N帧文件:

http://www.lua.org/manual/5.1/manual.html#5.9

请注意,这可能相当慢,所以如果你担心这些事情,那么你不想在快速路径上做这件事。

答案 6 :(得分:0)

arg[0]:match('.*\\')

如果返回nil,请尝试使用.\*\\\更改.*/arg[0]更改debug.getinfo(1).short_src

但我发现这是获取当前目录的最佳和最短的方式。

您当然可以使用..运算符附加您要查找的文件。它看起来像这样:

arg[0]:match('.*\\')..'file.lua'

答案 7 :(得分:0)

如果你想要实际路径:

path.dirname(path.abspath(debug.getinfo(1).short_src))

否则将其用于完整文件路径:

path.abspath(debug.getinfo(1).short_src)

答案 8 :(得分:0)

如果您想要包含文件名的真实路径,请使用以下

pathWithFilename=io.popen("cd"):read'*all'
print(pathWithFilename)

在Windows上测试。

<强>解释

io.popen - 将命令发送到命令行,并返回输出。

"cd" - 当您在cmd中输入时,您会将当前路径作为输出。

:read'*all' - 由于io.popen返回类似文件的对象,您可以使用相同类型的命令读取它。这将读取整个输出。

如果有人需要UNC路径:

function GetUNCPath(path,filename)
local DriveLetter=io.popen("cd "..path.." && echo %CD:~0,2%"):read'*l'
local NetPath=io.popen("net use "..DriveLetter):read'*all'
local NetRoot=NetPath:match("[^\n]*[\n]%a*%s*([%a*%p*]*)")
local PathTMP=io.popen("cd "..path.." && cd"):read'*l'
PathTMP=PathTMP:sub(3,-1)
UNCPath=NetRoot..PathTMP.."\\"..filename
return UNCPath
end

答案 9 :(得分:0)

我编写了一个函数getScriptDir,它使用了一些其他人建议的调试信息,但这个函数每次都会起作用(至少在Windows中)。但事情是有相当多的代码行,因为它使用了我创建的另一个函数string.cut,它将每个给定模式的字符串分开,并将其放入表中。

function string.cut(s,pattern)
  if pattern == nil then pattern = " " end
  local cutstring = {}
  local i1 = 0
  repeat
    i2 = nil
    local i2 = string.find(s,pattern,i1+1)
    if i2 == nil then i2 = string.len(s)+1 end
    table.insert(cutstring,string.sub(s,i1+1,i2-1))
    i1 = i2
  until i2 == string.len(s)+1
  return cutstring
end

function getScriptDir(source)
  if source == nil then
    source = debug.getinfo(1).source
  end
  local pwd1 = (io.popen("echo %cd%"):read("*l")):gsub("\\","/")
  local pwd2 = source:sub(2):gsub("\\","/")
  local pwd = ""
  if pwd2:sub(2,3) == ":/" then
    pwd = pwd2:sub(1,pwd2:find("[^/]*%.lua")-1)
  else
    local path1 = string.cut(pwd1:sub(4),"/")
    local path2 = string.cut(pwd2,"/")
    for i = 1,#path2-1 do
      if path2[i] == ".." then
        table.remove(path1)
      else
        table.insert(path1,path2[i])
      end
    end
    pwd = pwd1:sub(1,3)
    for i = 1,#path1 do
      pwd = pwd..path1[i].."/"
    end
  end
  return pwd
end

注意:如果您想在Windows以外的其他操作系统中使用此功能,则必须将第15行中的io.popen("echo %cd%")更改为任何命令您在操作系统中显示工作目录,例如适用于Linux的io.popen("pwd")第18行中的pwd2:sub(2,3) == ":/" 代表操作系统中根目录的任何内容,例如:适用于Linux的pwd2:sub(1,1) == "/"

注2:如果您在调用时没有通过source向函数提供debug.getinfo(1).source变量,那么它将返回到目录的路径包含此功能的文件。因此,如果您想获取通过dofileloadfile调用的文件的目录,则必须为其提供源代码,如下所示:getScriptDir(debug.getinfo(1).source)