Подтвердить что ты не робот

Получить содержащий путь файла lua

Мне интересно, есть ли способ получить путь к текущему исполняемому файлу lua script?

Это не текущий рабочий каталог, который может быть совершенно другим. Я знаю luafilesystem позволит мне получить текущий рабочий каталог, но он, похоже, не может сказать текущее выполнение script файл.

Спасибо

EDIT: Я не запускаюсь из стандартного интерпретатора командной строки, я выполняю скрипты из двоичного кода С++ через luabind.

4b9b3361

Ответ 1

Если Lua script выполняется стандартным интерпретатором командной строки, попробуйте arg[0].

Ответ 2

Это более элегантный способ:

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

print(script_path())

Ответ 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$ 

Это доступно из API C lua_getinfo

Ответ 4

Единственный надежный способ получить то, что вы хотите, - заменить 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.

Функции extractFilePath, isRelativePath и currentDir не являются функциями Lua; вам придется писать их самостоятельно. Функция extractFilePath вытаскивает строку пути из имени файла. isRelativePath берет путь и возвращает, является ли данный путь относительным путем. currentDir просто возвращает текущий каталог. Кроме того, вам нужно будет использовать "\" вместо "/" на машинах Windows.

Эта функция сохраняет путь в глобальном названии path. Вы можете изменить это, как хотите.

Ответ 5

Самая короткая форма, которую я нашел, выглядит следующим образом:

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

Индекс 1, 2- другой - зависит от того, какую функцию в стеке вызовов вы хотите запросить. 1 - последняя функция (где вы находитесь). Если вы работаете в глобальном контексте, то, вероятно, 2 более подходит (не проверял сам)

Ответ 6

Посмотрите библиотеку отладки Lua, которая является частью стандартного дистрибутива Lua. Вы можете использовать debug.getinfo для поиска текущего файла или файла N кадров в стеке вызовов:

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

Обратите внимание, что это, вероятно, довольно медленно, поэтому вы не хотите делать это на быстром пути, если вас беспокоят такие вещи.

Ответ 7

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

Если он возвращает nil, попробуйте изменить .\*\\\ на .*/ и arg[0] на debug.getinfo(1).short_src.

Но я считаю, что это лучший и самый короткий способ получить текущий каталог.

Вы можете, конечно, добавить файл, который вы ищете, с помощью оператора ... Он будет выглядеть примерно так:

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

Ответ 8

если вы хотите фактический путь:

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

else использовать это для полного пути к файлу:

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

Ответ 9

Если вам нужен реальный путь, включая имя файла, просто используйте следующие

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

Ответ 10

Я написал функцию 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, вам нужно изменить io.popen("echo %cd%") в строке 15 на любую команду, которая дает вам подарок рабочий каталог в вашей ОС, например io.popen("pwd") для Linux и pwd2:sub(2,3) == ":/" в строке 18, что представляет собой корневой каталог в вашей ОС, например. pwd2:sub(1,1) == "/" для Linux.

Примечание2:, если вы не предоставляете переменную source функции через debug.getinfo(1).source при ее вызове, она вернет путь к каталогу файла, содержащего эту функцию. Поэтому, если вы хотите получить каталог файла, который вы вызвали через dofile или loadfile, вам нужно будет предоставить ему источник, например: getScriptDir(debug.getinfo(1).source).