Let’s say I have a path like "./foo"
. How do I check whether it points to a file or to a directory? On UNIX, I’d expect to issue a stat
syscall and look at the st_mode
. Looking at the Zig fs api though, there’s statFIle
and Dir.stat
, so it looks like Zig wants me to preemptively know the kind of the thing I want to stat?
Not sure if it works on every platform, but there is os.system.stat()
which on linux seems equivalent to stat(2)
.
Otherwise there is std.c.stat()
but it requires libc.
I wrote this test to make sure I wasn’t lying:
test "stat()" {
var stat_buf: os.Stat = undefined;
{
const result = os.system.stat("/etc", &stat_buf);
try expectEqual(result, 0);
const mode = stat_buf.mode & os.S.IFMT;
try expectEqual(mode, os.S.IFDIR);
}
{
const result = os.system.stat("/etc/hostname", &stat_buf);
try expectEqual(result, 0);
const mode = stat_buf.mode & os.S.IFMT;
try expectEqual(mode, os.S.IFREG);
}
}
I don’t know if that helps.
I think you can use statFile
on either files or dirs
const filename = "/home"; //"src"; //"build.zig";
const stat = try std.fs.cwd().statFile(filename);
switch (stat.kind) {
.directory => std.debug.print("dir!\n", .{}),
.file => std.debug.print("file!\n", .{}),
else => std.debug.print("{s}\n", .{@tagName(stat.kind)}),
}
tested on zig version 0.11.0-dev.3803+7ad104227
Does it work on Windows? From the source code, it seems that windows is a bit more picky about the kind of thing:
You’re right that Windows would fail with error.IsDir
(and in theory every platform should but see Platform specific error.IsDir behavior in fs.Dir.openFile · Issue #5732 · ziglang/zig · GitHub).
I think there is a missing Dir.openAny
API in std.fs
, as this limitation for openFile
on Windows is self-imposed, and there’s currently no Dir
API to get the .filter = .any
behavior on Windows.
Alternatively, openFile
could drop the error.IsDir
error from its errorset and then make all platforms conform with that behavior (which is already the case for Linux at least).
This is also something that came up when @marler8997 was writing an ls
command for Windows and he ended up having to write a function using std.os.windows.OpenFile
:
On the flipside, I had to write a openFileNotDir
to get consistent openFile
behavior on every platform: