# Get CWD path without \`realPath\`

**URL:** <https://ziggit.dev/t/get-cwd-path-without-realpath/16293>\
**Category:** Help\
**Tags:** io\
**Created:** [June 22, 2026, 2:55pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293 "2026-06-22T14:55:57Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![odeuce](https://ziggit.dev/user_avatar/ziggit.dev/odeuce/32/9198_2.png) [@odeuce](https://ziggit.dev/u/odeuce)\
**Post date:** [June 22, 2026, 2:55pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/1 "2026-06-22T14:55:57Z")

</div>

Getting started with Zig and trying to write a simple “print working directory” type of command. I’ve read the docs for std.Io.Dir and seen the `realPath` function and it’s siblings and the advice not to use it. Tried anyway and got an `error.FileNotFound`.

What is the idiomatic way to get a directory’s path as a string? Here’s the method I tried…

```zig
test "read file" {
    var base: [1024]u8 = undefined;
    const out_buffer: []u8 = base[0..];
    const io = std.testing.io;
    const cwd = std.Io.Dir.cwd();
    const path_length = try cwd.realPath(io, out_buffer);
    std.debug.print("CWD: {any} {any}", .{ out_buffer, path_length });
}

```

Any help appreciated.

Edit: I’m using Mac OS.

---

<div class="post-metadata">

**Author:** ![miagi](https://ziggit.dev/user_avatar/ziggit.dev/miagi/32/6745_2.png) [@miagi](https://ziggit.dev/u/miagi)\
**Post date:** [June 22, 2026, 3:08pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/2 "2026-06-22T15:08:25Z")

</div>

Hi, and welcome to Ziggit 🙂  
I know of [std.process.currentPath()](https://ziglang.org/documentation/master/std/#std.process.currentPath). It returns current working directory of the executed program.

---

<div class="post-metadata">

**Author:** ![alanza](https://ziggit.dev/user_avatar/ziggit.dev/alanza/32/6006_2.png) [@alanza](https://ziggit.dev/u/alanza)\
**Post date:** [June 22, 2026, 4:47pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/3 "2026-06-22T16:47:20Z")

</div>

I think you’re slightly misusing the function; maybe because `cwd()` is special on macOS? Anyway, this works:

```zig
const std = @import("std");

test {
    var base: [1024]u8 = undefined;
    const io = std.testing.io;
    const cwd: std.Io.Dir = .cwd();
    const pwd = try cwd.openFile(io, ".", .{});
    defer pwd.close(io);
    const len = try pwd.realPath(io, &base);
    std.debug.print("CWD: {s}", .{base[0..len]});
}

```

---

<div class="post-metadata">

**Author:** ![lalinsky](https://ziggit.dev/user_avatar/ziggit.dev/lalinsky/32/3720_2.png) [@lalinsky](https://ziggit.dev/u/lalinsky)\
**Post date:** [June 22, 2026, 5:11pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/4 "2026-06-22T17:11:09Z")

</div>

Be aware that `realPath` is not well supported across operating systems.

---

<div class="post-metadata">

**Author:** ![odeuce](https://ziggit.dev/user_avatar/ziggit.dev/odeuce/32/9198_2.png) [@odeuce](https://ziggit.dev/u/odeuce)\
**Post date:** [June 22, 2026, 5:23pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/5 "2026-06-22T17:23:44Z")

</div>

@lalinsky that was my original question. The docs mention the lack of OS support, but don’t offer an alternative means of getting a path from a File or Dir object, nor a way to test for OS support.

---

<div class="post-metadata">

**Author:** ![lalinsky](https://ziggit.dev/user_avatar/ziggit.dev/lalinsky/32/3720_2.png) [@lalinsky](https://ziggit.dev/u/lalinsky)\
**Post date:** [June 22, 2026, 5:54pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/6 "2026-06-22T17:54:14Z")

</div>

You need to architecture your app so that you don’t need the path, or if you need it, you maintain it separately.

---

<div class="post-metadata">

**Author:** ![KilianHanich](https://ziggit.dev/user_avatar/ziggit.dev/kilianhanich/32/8254_2.png) [@KilianHanich](https://ziggit.dev/u/KilianHanich)\
**Post date:** [June 22, 2026, 7:23pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/7 "2026-06-22T19:23:35Z")

</div>

With the limitation that it thinks that you can’t have a longer path than `MAX_PATH`, which isn’t actually the case (at least on Unix-likes).

No, really, try it out. Here a small shell snippet which creates such a path and moves you inside of it:

```sh
for i in {1..10000}
do
    mkdir directory
    cd directory
done
pwd

```

But if you think about it, you CAN’T actually have a maximum path length.

And it’s very simple to explain why:  
Let’s assume there is such a maximum length.

1. Mount a disk under `/mnt`.
2. Create a path which fully uses the maximum length up.
3. Unmount the disk.
4. Create another maximum path which uses the maximum path up fully or even just slightly less.
5. Mount the disk again but now under that newly created path.
6. You now have a path which is in total longer than the maximum path.

`MAX_PATH` is only actually used as the maximum length you can use in a single syscall (on Linux) for some syscalls but besides that is just an arbitrary value (and explicitly mentioned in Linux’ documentation to be arbitrary).

---

<div class="post-metadata">

**Author:** ![SuXYIO](https://ziggit.dev/user_avatar/ziggit.dev/suxyio/32/10366_2.png) [@SuXYIO](https://ziggit.dev/u/SuXYIO)\
**Post date:** [October 23, 2026, 2:39pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/8 "2026-10-23T14:39:45Z")

</div>

Maybe just use `cwd.realPathFileAlloc`?  
saves the work of opening a file and keeping a buffer  
example:

```zig
const std = @import("std");

test {
    const io = std.testing.io;
    const gpa = std.testing.allocator;
    const cwd: std.Io.Dir = .cwd();

    const path = try cwd.realPathFileAlloc(io, ".", gpa);
    defer gpa.free(path);
    std.debug.print("{s}\n", .{path});
}

```

---

<div class="post-metadata">

**Author:** ![SuXYIO](https://ziggit.dev/user_avatar/ziggit.dev/suxyio/32/10366_2.png) [@SuXYIO](https://ziggit.dev/u/SuXYIO)\
**Post date:** [October 23, 2026, 2:45pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/9 "2026-10-23T14:45:32Z")

</div>

btw im also implementing a `pwd` like tool,  
and the common `pwd` has _logical_ and _physical_ modes,  
quote from manpages:

```plaintext
-L, --logical
       use PWD from environment, even if it contains symlinks

-P, --physical
       resolve all symlinks

```

After testing, `realPath` family and `std.process.currentPath` are both giving physical paths,  
so is there a way to obtain the logical path?

---

<div class="post-metadata">

**Author:** ![SuXYIO](https://ziggit.dev/user_avatar/ziggit.dev/suxyio/32/10366_2.png) [@SuXYIO](https://ziggit.dev/u/SuXYIO)\
**Post date:** [October 23, 2026, 2:49pm UTC](https://ziggit.dev/t/get-cwd-path-without-realpath/16293/10 "2026-10-23T14:49:19Z")

</div>

A known solution is via `init.environ_map.get("PWD")`,  
but it is affected by the environ, which is not the behavior of shell `pwd` and busybox `pwd`:

```console
$ which pwd
pwd: shell built-in command

$ PWD=foo pwd -L
/correctpath

$ PWD=foo busybox pwd -L
/correctpath

$ PWD=foo ./mypwd -L
foo

```

I also looked a bit in the busybox source, and it seems to be just getting the environ, but it’s still not influenced by it in the test above

> <https://github.com/mirror/busybox/blob/371fe9f71d445d18be28c82a2a6d82115c8af19d/coreutils/pwd.c#L37>
