現在実行中のluaスクリプトファイルへのパスを取得する方法があるかどうか疑問に思っていますか?
これは特に現在の作業ディレクトリではなく、完全に異なる可能性があります。 luafilesystem で現在の作業ディレクトリを取得できることはわかっていますが、現在実行中のスクリプトファイルを認識できないようです。
ありがとう
編集:私は標準のコマンドラインインタープリターから実行していません。C++バイナリから luabind を介してスクリプトを実行しています。
Luaスクリプトが標準のコマンドラインインタープリターによって実行されている場合は、arg[0]
を試してください。
これはよりエレガントな方法です:
function script_path()
local str = debug.getinfo(2, "S").source:sub(2)
return str:match("(.*/)")
end
print(script_path())
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
必要なものを取得するための唯一の信頼できる方法は、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
というグローバルに格納します。あなたはそれを好きなように変えることができます。
私が見つけた最短のフォームは次のようになります。
debug.getinfo(1).source:match("@?(.*/)")
インデックス1、2-その他-クエリするコールスタック内の関数によって異なります。 1は最後に呼び出された関数です(あなたがいる場所)。グローバルコンテキストで実行している場合は、おそらく2がより適切です(自分でテストしていません)
_arg[0]:match('.*\\')
_
Nilが返される場合は、_.\*\\\
_を_.*/
_に、_arg[0]
_をdebug.getinfo(1).short_src
に変更してみてください。
しかし、これが現在のディレクトリを取得するための最良かつ最短の方法であることがわかりました。
もちろん、探しているファイルを_..
_演算子で追加することもできます。次のようになります。
_arg[0]:match('.*\\')..'file.lua'
_
ファイル名を含む実際のパスが必要な場合は、次を使用してください
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
標準のLuaディストリビューションの一部であるLuaデバッグライブラリをご覧ください。 debug.getinfoを使用して、現在のファイル、またはコールスタックのNフレーム上のファイルを見つけることができます。
http://www.lua.org/manual/5.1/manual.html#5.9
これはおそらくかなり遅いので、そのようなことを心配している場合は、高速パスで実行したいことではないことに注意してください。
他の数人が提案したようにデバッグ情報を使用する関数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")
、行18のpwd2:sub(2,3) == ":/"
は、OSのルートディレクトリを表すものになります。 Linuxの場合はpwd2:sub(1,1) == "/"
。
注2:呼び出し時にdebug.getinfo(1).source
を介して関数にsource
変数を指定しない場合、-のディレクトリへのパスが返されます。 この関数を含むファイル。したがって、dofile
またはloadfile
を介して呼び出したファイルのディレクトリを取得する場合は、getScriptDir(debug.getinfo(1).source)
のようにソースを指定する必要があります。
実際のパスが必要な場合:
path.dirname(path.abspath(debug.getinfo(1).short_src))
それ以外の場合は、これを完全なファイルパスに使用します。
path.abspath(debug.getinfo(1).short_src)