How to check if path points to a file or a directory?

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?

3 Likes

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.

1 Like

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

2 Likes

Does it work on Windows? From the source code, it seems that windows is a bit more picky about the kind of thing:

1 Like

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:

5 Likes