Skip to content

Instantly share code, notes, and snippets.

@j5ndev
Forked from yougg/tree.zig
Created August 8, 2025 22:03
Show Gist options
  • Save j5ndev/048153ede373f68b9d4d7ff3951f0e03 to your computer and use it in GitHub Desktop.
Save j5ndev/048153ede373f68b9d4d7ff3951f0e03 to your computer and use it in GitHub Desktop.

Revisions

  1. @yougg yougg created this gist Jul 31, 2025.
    73 changes: 73 additions & 0 deletions tree.zig
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    // zig version: 0.14.1+

    const std = @import("std");

    const Entry = struct {
    name: []const u8,
    kind: std.fs.Dir.Entry.Kind,
    };

    pub fn main() !void {
    const allocator = std.heap.page_allocator;
    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);
    const root = if (args.len > 1) args[1] else ".";
    var stdout = std.io.getStdOut().writer();
    try stdout.print("{s}\n", .{root});
    try printDirectory(root, "", allocator, stdout);
    }

    const indent_unicode = "│ ";
    const indent_space = " ";
    const suffix_last = "└──";
    const suffix_mid = "├──";

    fn printDirectory(path: []const u8, indent: []const u8, allocator: std.mem.Allocator, stdout: anytype) !void {
    var dir = try std.fs.cwd().openDir(path, .{ .iterate = true });
    defer dir.close();

    var entries = std.ArrayList(Entry).init(allocator);
    defer {
    for (entries.items) |entry| {
    allocator.free(entry.name);
    }
    entries.deinit();
    }

    var it = dir.iterate();
    while (try it.next()) |entry| {
    const name_copy = try allocator.dupe(u8, entry.name);
    try entries.append(Entry{
    .name = name_copy,
    .kind = entry.kind,
    });
    }

    const count = entries.items.len;
    for (entries.items, 0..) |entry, index| {
    const is_last = index + 1 == count;
    const middle = if (is_last) indent_space else indent_unicode;
    const suffix = if (is_last) suffix_last else suffix_mid;

    var buf: [512]u8 = undefined;
    const prefix = try std.fmt.bufPrint(&buf, "{s}{s}", .{ indent, suffix });

    try stdout.print("{s} {s}\n", .{ prefix, entry.name });

    if (entry.kind == .directory) {
    const full_len = path.len + 1 + entry.name.len;
    var path_buf = try allocator.alloc(u8, full_len);
    defer allocator.free(path_buf);

    std.mem.copyForwards(u8, path_buf[0..path.len], path);
    path_buf[path.len] = '/';
    std.mem.copyForwards(u8, path_buf[path.len + 1 ..], entry.name);
    const sub_path = path_buf[0..full_len];

    var sub_buf: [512]u8 = undefined;
    const sub_indent = try std.fmt.bufPrint(&sub_buf, "{s}{s}", .{ indent, middle });

    try printDirectory(sub_path, sub_indent, allocator, stdout);
    }
    }
    }