std.fs.cwd() em Zig — Referência e Exemplos

std.fs.cwd() — Diretório de Trabalho Atual

A função std.fs.cwd() retorna um handle Dir que representa o diretório de trabalho atual (Current Working Directory) do processo. Este é o ponto de partida mais comum para operações de sistema de arquivos em Zig, pois permite abrir arquivos e diretórios usando caminhos relativos.

Visão Geral

pub fn cwd() Dir

A função retorna um Dir que pode ser usado para todas as operações de arquivo e diretório relativas ao diretório atual. O Dir retornado não precisa ser fechado (não é um descritor de diretório alocado).

Operações Principais via cwd()

O Dir retornado por cwd() oferece diversos métodos:

Abertura e Criação de Arquivos

// Abrir arquivo existente para leitura
pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File

// Criar ou truncar arquivo
pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File

// Deletar arquivo
pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void

// Renomear arquivo
pub fn rename(self: Dir, old: []const u8, new: []const u8) RenameError!void

Operações de Diretório

// Abrir subdiretório
pub fn openDir(self: Dir, sub_path: []const u8, flags: Dir.OpenDirOptions) OpenError!Dir

// Criar diretório
pub fn makeDir(self: Dir, sub_path: []const u8) MakeDirError!void

// Criar diretórios recursivamente
pub fn makePath(self: Dir, sub_path: []const u8) MakePathError!void

// Deletar diretório vazio
pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void

// Deletar diretório e todo seu conteúdo
pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void

Leitura Rápida

// Ler arquivo inteiro em memória (com alocação)
pub fn readFileAlloc(self: Dir, allocator: Allocator, file_path: []const u8, max_bytes: usize) ![]u8

Exemplo 1: Operações Básicas de Arquivo

const std = @import("std");

pub fn main() !void {
    const cwd = std.fs.cwd();

    // Criar um arquivo e escrever conteúdo
    {
        const file = try cwd.createFile("notas.txt", .{});
        defer file.close();
        try file.writeAll("Lembrete: estudar Zig hoje!\n");
        try file.writeAll("Segunda nota: praticar alocadores.\n");
    }

    // Abrir e ler o arquivo
    {
        const file = try cwd.openFile("notas.txt", .{});
        defer file.close();

        var buf: [4096]u8 = undefined;
        const n = try file.readAll(&buf);
        std.debug.print("Conteúdo ({d} bytes):\n{s}\n", .{ n, buf[0..n] });
    }

    // Renomear
    try cwd.rename("notas.txt", "notas_backup.txt");
    std.debug.print("Arquivo renomeado.\n", .{});

    // Limpar
    try cwd.deleteFile("notas_backup.txt");
    std.debug.print("Arquivo removido.\n", .{});
}

Exemplo 2: Criação e Navegação de Diretórios

const std = @import("std");

pub fn main() !void {
    const cwd = std.fs.cwd();

    // Criar estrutura de diretórios
    try cwd.makePath("projeto/src");
    try cwd.makePath("projeto/tests");
    try cwd.makePath("projeto/docs");
    std.debug.print("Estrutura de diretórios criada.\n", .{});

    // Criar arquivos dentro da estrutura
    {
        const main_file = try cwd.createFile("projeto/src/main.zig", .{});
        defer main_file.close();
        try main_file.writeAll("pub fn main() !void {}\n");
    }

    {
        const test_file = try cwd.createFile("projeto/tests/test_main.zig", .{});
        defer test_file.close();
        try test_file.writeAll("test \"básico\" { }\n");
    }

    // Abrir subdiretório e operar nele
    var src_dir = try cwd.openDir("projeto/src", .{ .iterate = true });
    defer src_dir.close();

    var iter = src_dir.iterate();
    std.debug.print("\nArquivos em projeto/src/:\n", .{});
    while (try iter.next()) |entrada| {
        std.debug.print("  {s}\n", .{entrada.name});
    }

    // Limpar tudo
    try cwd.deleteTree("projeto");
    std.debug.print("\nEstrutura removida.\n", .{});
}

Exemplo 3: Leitura de Arquivo com Alocação

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const cwd = std.fs.cwd();

    // Preparar arquivo de teste
    {
        const f = try cwd.createFile("config.ini", .{});
        defer f.close();
        try f.writeAll("[geral]\nnome=MeuApp\nversao=1.0\n[banco]\nhost=localhost\nporta=5432\n");
    }

    // Ler arquivo inteiro
    const conteudo = try cwd.readFileAlloc(allocator, "config.ini", 1024 * 1024);
    defer allocator.free(conteudo);

    // Processar linhas
    var iter = std.mem.splitSequence(u8, conteudo, "\n");
    while (iter.next()) |linha| {
        if (linha.len == 0) continue;
        if (linha[0] == '[') {
            std.debug.print("\nSeção: {s}\n", .{linha});
        } else {
            std.debug.print("  {s}\n", .{linha});
        }
    }

    try cwd.deleteFile("config.ini");
}

Padrões Comuns

Verificação de Existência de Arquivo

O Zig não tem uma função exists() dedicada. O padrão idiomático é tentar abrir:

fn arquivoExiste(caminho: []const u8) bool {
    const arquivo = std.fs.cwd().openFile(caminho, .{}) catch return false;
    arquivo.close();
    return true;
}

Escrita Atômica

Para evitar corrupção em caso de falha, escreva em arquivo temporário e renomeie:

{
    const tmp = try cwd.createFile("dados.tmp", .{});
    defer tmp.close();
    try tmp.writeAll(novos_dados);
}
try cwd.rename("dados.tmp", "dados.txt");

Obter Caminho Absoluto

var buf: [std.fs.max_path_bytes]u8 = undefined;
const caminho_abs = try std.fs.cwd().realpath("arquivo.txt", &buf);
std.debug.print("Caminho absoluto: {s}\n", .{caminho_abs});

Módulos Relacionados

Tutoriais e Receitas Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.