web-dev-qa-db-ja.com

luaファイルの包含パスを取得します

現在実行中のluaスクリプトファイルへのパスを取得する方法があるかどうか疑問に思っていますか?

これは特に現在の作業ディレクトリではなく、完全に異なる可能性があります。 luafilesystem で現在の作業ディレクトリを取得できることはわかっていますが、現在実行中のスクリプトファイルを認識できないようです。

ありがとう

編集:私は標準のコマンドラインインタープリターから実行していません。C++バイナリから luabind を介してスクリプトを実行しています。

19
radman

Luaスクリプトが標準のコマンドラインインタープリターによって実行されている場合は、arg[0]を試してください。

6
lhf

これはよりエレガントな方法です:

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

print(script_path())
15
anthonygore

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$ 

これはCAPIから利用できます lua_getinfo

3
Doug Currie

必要なものを取得するための唯一の信頼できる方法は、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.

関数extractFilePathisRelativePath、およびcurrentDirはLua関数ではありません。あなたはそれらを自分で書かなければならないでしょう。 extractFilePath関数は、ファイル名からパス文字列を引き出します。 isRelativePathはパスを取り、指定されたパスが相対パス名であるかどうかを返します。 currentDirは単に現在のディレクトリを返します。また、Windowsマシンでは「/」の代わりに「\」を使用する必要があります。

この関数は、パスをpathというグローバルに格納します。あなたはそれを好きなように変えることができます。

3
Nicol Bolas

私が見つけた最短のフォームは次のようになります。

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

インデックス1、2-その他-クエリするコールスタック内の関数によって異なります。 1は最後に呼び出された関数です(あなたがいる場所)。グローバルコンテキストで実行している場合は、おそらく2がより適切です(自分でテストしていません)

2
TarmoPikaro
_arg[0]:match('.*\\')
_

Nilが返される場合は、_.\*\\\_を_.*/_に、_arg[0]_をdebug.getinfo(1).short_srcに変更してみてください。

しかし、これが現在のディレクトリを取得するための最良かつ最短の方法であることがわかりました。

もちろん、探しているファイルを_.._演算子で追加することもできます。次のようになります。

_arg[0]:match('.*\\')..'file.lua'
_
0
Coop Jmz

ファイル名を含む実際のパスが必要な場合は、次を使用してください

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
0
WalyKu

標準のLuaディストリビューションの一部であるLuaデバッグライブラリをご覧ください。 debug.getinfoを使用して、現在のファイル、またはコールスタックのNフレーム上のファイルを見つけることができます。

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

これはおそらくかなり遅いので、そのようなことを心配している場合は、高速パスで実行したいことではないことに注意してください。

0
acm

他の数人が提案したようにデバッグ情報を使用する関数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以外のOSで使用する場合は、15行目io.popen("echo %cd%")を任意のコマンドに変更する必要があります。 OSに作業ディレクトリを表示します。例: Linuxの場合はio.popen("pwd")行18pwd2:sub(2,3) == ":/"は、OSのルートディレクトリを表すものになります。 Linuxの場合はpwd2:sub(1,1) == "/"

注2:呼び出し時にdebug.getinfo(1).sourceを介して関数にsource変数を指定しない場合、-のディレクトリへのパスが返されます。 この関数を含むファイル。したがって、dofileまたはloadfileを介して呼び出したファイルのディレクトリを取得する場合は、getScriptDir(debug.getinfo(1).source)のようにソースを指定する必要があります。

0
Amine Kchouk

実際のパスが必要な場合:

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

それ以外の場合は、これを完全なファイルパスに使用します。

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