如何检查 lua 中是否存在目录,如果可能的话最好不使用 LuaFileSystem 模块?
尝试做类似Python行的事情:
os.path.isdir(path)
这是一种在 Unix 和 Windows 上都适用的方式,无需任何外部依赖:
--- Check if a file or directory exists in this path
function exists(file)
local ok, err, code = os.rename(file, file)
if not ok then
if code == 13 then
-- Permission denied, but it exists
return true
end
end
return ok, err
end
--- Check if a directory exists in this path
function isdir(path)
-- "/" works on both Unix and Windows
return exists(path.."/")
end
问题在于,现有的 Lua 发行版(几乎)只包含标准 C 中指定的功能。标准 C 没有假设实际上存在任何特定类型的文件系统(甚至是操作系统) ),因此
os
和 io
模块不提供标准 C 库中不可用的访问信息。
如果您尝试使用纯标准 C 进行编码,您也会遇到同样的问题。
您有机会通过尝试使用该文件夹来了解该文件夹是否隐式存在。如果您希望它存在并且可供您写入,则在其中创建一个临时文件,如果成功,则该文件夹存在。当然,如果失败,您可能无法区分不存在的文件夹和权限不足。
到目前为止,获得特定答案的最轻量级答案是对那些提供您所需信息的特定于操作系统的函数调用的精简绑定。如果您可以接受 lua Alien 模块,那么您可以在其他纯 Lua 中进行绑定。
更简单,但稍微重一点的是接受Lua文件系统。它提供了一个可移植模块,支持人们可能想要了解的有关文件和文件系统的大多数内容。
如果您特别想避免使用 LFS 库,Lua Posix 库 有一个 stat() 接口。
require 'posix'
function isdir(fn)
return (posix.stat(fn, "type") == 'directory')
end
嗯,5.1 参考手册在 操作系统表 中没有任何内容,但是如果您使用 Nixstaller,您将获得
os.fileexists
来准确了解您所解释的内容。
如果您有能力摆弄一下,或者如果您知道将在什么操作系统上运行,您可能会使用标准操作系统库的
os.execute
以及一些系统调用来识别文件是否存在。
甚至比 os.execute 更好的可能是 os.rename:
os.rename(oldname, newname)
将名为
的文件重命名为oldname
。 如果该函数失败,则返回 nil,加上一个描述的字符串 错误。newname
您可以尝试将旧名称和新名称设置为相同 - 不过,您可能没有写入权限,因此它可能会失败,因为您无法写入,即使您可以读取。在这种情况下,您必须解析返回的错误字符串并推断您是否可以写入,或者您必须尝试执行需要现有文件的函数,并将其包装在
pcall
.
您还可以使用“paths”包。 这里是包的链接
然后在 Lua 中做:
require 'paths'
if paths.dirp('your_desired_directory') then
print 'it exists'
else
print 'it does not exist'
end
这是针对windows平台进行测试的。其实很简单:
local function directory_exists( sPath )
if type( sPath ) ~= "string" then return false end
local response = os.execute( "cd " .. sPath )
if response == 0 then
return true
end
return false
end
显然,这可能不适用于其他操作系统。但对于 Windows 用户来说,这可能是一个解决方案:)
我使用这些(但我实际上检查了错误):
require("lfs")
-- no function checks for errors.
-- you should check for them
function isFile(name)
if type(name)~="string" then return false end
if not isDir(name) then
return os.rename(name,name) and true or false
-- note that the short evaluation is to
-- return false instead of a possible nil
end
return false
end
function isFileOrDir(name)
if type(name)~="string" then return false end
return os.rename(name, name) and true or false
end
function isDir(name)
if type(name)~="string" then return false end
local cd = lfs.currentdir()
local is = lfs.chdir(name) and true or false
lfs.chdir(cd)
return is
end
os.rename(name1, name2) 会将 name1 重命名为 name2。使用相同的名称,什么都不会改变(除非有一个严重的错误)。如果一切顺利,则返回 true,否则返回 nil 和错误消息。你说你不想使用 lfs。如果你不这样做,你就无法区分文件和目录,而不尝试打开文件(这有点慢,但还好)。
所以没有 LuaFileSystem
-- no require("lfs")
function exists(name)
if type(name)~="string" then return false end
return os.rename(name,name) and true or false
end
function isFile(name)
if type(name)~="string" then return false end
if not exists(name) then return false end
local f = io.open(name)
if f then
f:close()
return true
end
return false
end
function isDir(name)
return (exists(name) and not isFile(name))
end
看起来更短,但需要更长的时间...... 打开文件也是有风险的,因为你应该使用lfs。 如果您不关心性能(和错误处理-.-),您可以使用它。
祝你编码愉快!
这是检查文件夹是否存在且不存在任何外部库依赖的简单方法:)
function directory_exists(path)
local f = io.popen("cd " .. path)
local ff = f:read("*all")
if (ff:find("ItemNotFoundException")) then
return false
else
return true
end
end
print(directory_exists("C:\\Users"))
print(directory_exists("C:\\ThisFolder\\IsNotHere"))
如果你将上面的内容复制并粘贴到 Lua 中,你应该会看到
false
true
祝你好运:)
这感觉太简单了,我觉得这是有原因的,没有其他人这样做过。
但它可以在我的机器(Ubuntu focus)上运行,适用于文件和目录。
但是它确实说存在但禁止的文件不存在。
对于快速脚本和/或几个文件:
function exists(path)
return (io.open(path,"r") ~= nil)
end
好的做法:
function exists(path)
local file = io.open(path,"r")
if (file ~= nil) then
io.close(file)
return true
else
return false
end
end
对于 Linux 用户:
function dir_exists( path )
if type( path ) ~= 'string' then
error('input error')
return false
end
local response = os.execute( 'cd ' .. path )
if response == nil then
return false
end
return response
end
我在 Linux 中执行此操作的首选方法是
if os.execute '[ -e "/home" ]' then
io.write "it exists"
if os.execute '[ -d "/home" ]' then
io.write " and is a directory"
end
io.write "\n"
end
或者,将其放入函数中:
function is_dir(path)
return os.execute(('[ -d "%s" ]'):format(path))
end -- note that this implementation will return some more values
在openwrt中广泛使用的一个包,
有很多有用的功能,而且易于使用
文档: http://openwrt.github.io/luci/api/modules/nixio.fs.html#nixio.fs.stat
> fs = require'nixio.fs'
> st = fs.stat('/tmp')
> = st.type=='dir'
true
> = fs.lstat'/var'.type=='lnk'
true
> = fs.stat'/bin/sh'.type=='reg'
true
测试:
> = pj(fs.stat'/var')
{
"dev": 17,
"type": "dir",
"modedec": 755,
"rdev": 0,
"nlink": 28,
"atime": 1617348683,
"blocks": 0,
"modestr": "rwxr-xr-x",
"ino": 1136,
"mtime": 1666474113,
"gid": 0,
"blksize": 4096,
"ctime": 1666474113,
"uid": 0,
"size": 1960
}
> = pj(fs.lstat'/var')
{
"dev": 19,
"type": "lnk",
"modedec": 777,
"rdev": 0,
"nlink": 1,
"atime": 1613402557,
"blocks": 0,
"modestr": "rwxrwxrwx",
"ino": 1003,
"mtime": 1613402557,
"gid": 0,
"blksize": 1024,
"ctime": 1613402557,
"uid": 0,
"size": 3
}
外壳测试操作员
[-e路径]
[-f路径]
[-d 路径]
[-L路径]
低级别都依赖于这个系统调用。
$ strace test -e /var |& grep stat | tail -1
stat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
$ strace test -f /var |& grep stat | tail -1
stat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
$ strace test -d /var |& grep stat | tail -1
stat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
$ strace test -L /var |& grep stat | tail -1
lstat("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
您要尝试避免使用 LuaFileSystem,但为了完整性/比较,这里有一个使用它的答案:
local lfs = require "lfs"
function isdir(path)
return lfs.attributes(path, "mode") == "directory"
end
local function directory_exist(dir_path)
local f = io.popen('[ -d "' .. dir_path .. '" ] && echo -n y')
local result = f:read(1)
f:close()
return result == "y"
end
试试这个