lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


pocomane <pocomane_7a@pocomane.com> 于2020年1月30日周四 下午4:16写道:
>
> On Tue, Jan 21, 2020 at 8:20 AM Hongyi Zhao <hongyi.zhao@gmail.com> wrote:
> > Is there any robust and convenient methods for me to obtain the lua
> > script's (absolute/real) dirname and file name from within the script
> > itself?
>
> TL;DR. You can just go to the last snippet of code.
>
> The question could be split in the following:
> 1) What I mean for "Scirpt file"
> 2) How get info about where it is
> 3) How extract the absolute path
> 4) Split name and directory
>
> The 1) seems obvious but in lua you can execute code from hard disk,
> memory, you can get it from network or from a usb or rs232 device. So
> let's just restrict to cases where "Script file" make sense:
>
> a) The "Main script file", i.e. the one you pass to the lua standalone
> interpreter from the command line
> b) Any other file loaded by the main one through `require`
> c) A string passed to `load` with a third parameter that is a proper
> file reference
>
> These are all the ways you have to actually execute lua code. Note
> that an embedding application that calls lua, falls in the case c) as
> well as a lua C modules calling lua code.
>
> The info 2) is in `arg[0]` just for the case a). However, for all the
> cases you can use
>
> ```
> path = debug.getinfo(1,"S").source:sub(2)
> ```
>
> but remember that in c) what is returned is what you passed to `load`
> as third parameter (is up to you to specify correctly where you took
> the information).
>
> However the info returned can be a RELATIVE path, e.g.:
> - in a) could return `./main.lua` if you launched the script with `lua
> ./main.lua`
> - in b) `package.path='./module/?.lua' require 'mymodule' ` could
> return './module/mymodule.lua'
>
> Sadly, if you really need the abolute path 3), you have to rely on
> os-dependent tricks. For linux you can use popen and realpath:
>
> ```
> absolute = io.popen("realpath '"..path.."'", 'r'):read('a')
> absolute = absolute:gsub('[\n\r]*$','') -- needed to handle popen result
> ```
>
> This give you the absolute path to the file, so for the step 4) you
> need a bit of string parsing to split path and name, e.g.
> `absolute:match('^(.*/)([^/]-)$')`.
>
> So putting all togheter:
>
> ```
> local fullpath = debug.getinfo(1,"S").source:sub(2)
> fullpath = io.popen("realpath '"..fullpath.."'", 'r'):read('a')
> fullpath = fullpath:gsub('[\n\r]*$','')
>
> local dirname, filename = fullpath:match('^(.*/)([^/]-)$')
> dirname = dirname or ''
> filename = filename or fullpath
> ```

Wonderful, thanks a lot, it does the trick.

Regards

>


-- 
Hongsheng Zhao <hongyi.zhao@gmail.com>
Institute of Semiconductors, Chinese Academy of Sciences
GnuPG DSA: 0xD108493