使用Lua检查文件是否为目录

6
如果我有这段代码:
local f = io.open("../web/", "r")
print(io.type(f))

-- output: file

如何确定f是否指向一个目录?


我非常确定在那里f将会是空值,因为使用io.open打开一个目录应该会返回nil和一个字符串如error opening "../web/": is a directory(在Windows上我得到的是../web/: Permission denied)。 - Stuart P. Bentley
8个回答

9

ANSI C无法获取目录信息,因此普通的Lua无法提供该信息(因为Lua力求100%可移植性)。但是,您可以使用外部库,例如LuaFileSystem来识别目录。

《Lua编程》甚至明确说明了缺少目录功能:

作为一个更复杂的例子,让我们编写一个函数,返回给定目录的内容。Lua在其标准库中没有提供此功能,因为ANSI C没有这项工作的函数。

该示例继续展示如何自己使用C编写dir函数。


7

我在使用的库中发现了以下代码:

function is_dir(path)
    local f = io.open(path, "r")
    local ok, err, code = f:read(1)
    f:close()
    return code == 21
end

我不知道在Windows上的代码会是什么,但在Linux/BSD/OSX上它可以正常工作。


这也会对空文件返回“true”。 - blueyed

6

如果你这样做

local x,err=f:read(1)

然后你会在err中得到"是一个目录"的提示。


4
请注意,错误消息(如果来自系统)可能是本地化的,因此依赖它可能并不是一个好主意。 - Alexander Gladysh
当然,您可以通过在运行时故意引发错误来收集某些本地化系统错误消息的参考样本,并使用该目录进行决策...现在问题是错误列表本身也不是真正可移植的。例如,在一些符合标准的C环境中甚至可能没有目录的概念。 - RBerteig

5
Lua的默认库没有办法确定这一点。但是,您可以使用第三方 LuaFileSystem库来获得更高级的文件系统交互;它也是跨平台的。LuaFileSystem提供了lfs.attributes,您可以使用它来查询文件模式:
require "lfs"
function is_dir(path)
    -- lfs.attributes will error on a filename ending in '/'
    return path:sub(-1) == "/" or lfs.attributes(path, "mode") == "directory"
end

1
使用LFS。在苏联Lua中,可移植性伤害你。 - Puppy

3

至少对于UNIX系统:

if os.execute("cd '" .. f .. "'")
then print("Is a dir")
else print("Not a dir")
end

:)


0

首先检查路径是否可读(对于空文件也是nil ),然后再检查大小是否不为0。

function is_dir(path)
    f = io.open(path)
    return not f:read(0) and f:seek("end") ~= 0
end

0
function fs.isDir ( file )
if file == nil then return true end
if fs.exists(file) then
    os.execute("dir \""..userPath..file.."\" >> "..userPath.."\\Temp\\$temp")
    file = io.open(userPath.."\\Temp\\$temp","r")
    result = false
    for line in file:lines() do
        if string.find(line, "<DIR>") ~= nil then
            result = true
            break
        end
    end
    file:close()
    fs.delete("\\Temp\\$temp")
    if not (result == true or result == false) then
        return "Error"
    else
        return result
    end
else
    return false
end
end

这是我从之前发现的一个库中提取出来的一些代码。


很遗憾,我没有。但是我发现,如果你将userPath变量更改为你的项目所在的目录,创建Temp文件夹并在那里使用它,就不会出现任何错误。 - Marumaru
嗯,你怎么可能从一个库中提取东西而不知道你从哪里拿的呢?你应该始终给予应有的荣誉。 - Michael

0

由于问题没有指定可移植性的需求,在Linux/Unix系统上,您可以依赖于file命令:

function file(path)
  local p = io.popen(('file %q'):format(path))
  if p then
    local out = p:read():gsub('^[^:]-:%s*(%w+).*','%1')
    p:close()
    return out
  end
end

if file('/') == 'directory' then
  -- do something
end

已测试并可在Lua 5.1至5.4版本中运行


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接