Split PATH environment variable in Zig

const std = @import("std");

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);

    // Get the PATH environment variable
    const pathEnv = std.process.getEnvVarOwned(allocator, "PATH") catch {
        std.debug.print("Error: PATH environment variable not found\n", .{});
        return;
    };
    defer allocator.free(pathEnv);

    // Split PATH into individual directories
    var dirs = std.mem.splitScalar(u8, pathEnv, ':');

    while (dirs.next()) |dir| {
        std.debug.print("Directory: {s}\n", .{dir});
    }
}

This Zig program is a command line tool that retrieves and prints every directory listed in the system’s PATH environment variable. It begins by importing the standard library and defining a main() function that returns an error union !void, allowing it to propagate errors cleanly. Inside main(), it uses the page allocator to collect the program’s command-line arguments via std.process.argsAlloc(), immediately followed by a defer statement that guarantees the arguments will be freed when the function exits—preventing memory leaks even if an error occurs early.

The core functionality focuses on the PATH environment variable, which tells the operating system where to look for executable programs. The program attempts to retrieve an owned copy of PATH using std.process.getEnvVarOwned(), which allocates a fresh string that the caller must free. If PATH is unset (unlikely on most systems), it catches the error, prints a friendly message, and returns early. Another defer ensures this allocated string is always freed before exit. Once it has the PATH string, it uses std.mem.splitScalar to create an iterator that splits the string on the colon : character—the standard path separator on UNIX-like systems. A simple while loop then iterates over this splitter: each call to dirs.next() yields the next directory as a slice (or null when done), and the program prints each one on its own line with a “Directory:” prefix.

Save the code as splitPATH.zig and execute it:

$ zig version
0.15.2
$ zig run splitPATH.zig
Directory: /opt/homebrew/bin
Directory: /opt/homebrew/sbin
Directory: /usr/local/bin
Directory: /usr/bin
Directory: /bin
Directory: /usr/sbin
Directory: /sbin

Happy coding in Zig!