Como Copiar Arquivos em Zig
Copiar arquivos é uma operação fundamental em gerenciamento de dados, backups e instalação de software. Zig oferece funções na biblioteca padrão para cópia eficiente de arquivos.
Cópia Simples com copyFile
A forma mais direta de copiar um arquivo é com Dir.copyFile.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Copiar arquivo
try std.fs.cwd().copyFile("origem.txt", std.fs.cwd(), "destino.txt", .{});
try stdout.print("Arquivo copiado: origem.txt -> destino.txt\n", .{});
}
Cópia Manual com Buffer
Para ter mais controle sobre o processo de cópia, leia e escreva manualmente.
const std = @import("std");
fn copiarComBuffer(origem: []const u8, destino: []const u8) !u64 {
const arq_origem = try std.fs.cwd().openFile(origem, .{});
defer arq_origem.close();
const arq_destino = try std.fs.cwd().createFile(destino, .{});
defer arq_destino.close();
var buf: [8192]u8 = undefined;
var total: u64 = 0;
while (true) {
const n = try arq_origem.read(&buf);
if (n == 0) break;
try arq_destino.writeAll(buf[0..n]);
total += n;
}
return total;
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const bytes = try copiarComBuffer("dados.bin", "dados_backup.bin");
try stdout.print("Copiados {d} bytes\n", .{bytes});
}
Cópia com Progresso
Para arquivos grandes, mostre o progresso da cópia.
const std = @import("std");
fn copiarComProgresso(origem: []const u8, destino: []const u8) !void {
const stdout = std.io.getStdOut().writer();
const arq_origem = try std.fs.cwd().openFile(origem, .{});
defer arq_origem.close();
const stat = try arq_origem.stat();
const tamanho_total = stat.size;
const arq_destino = try std.fs.cwd().createFile(destino, .{});
defer arq_destino.close();
var buf: [32768]u8 = undefined;
var copiados: u64 = 0;
while (true) {
const n = try arq_origem.read(&buf);
if (n == 0) break;
try arq_destino.writeAll(buf[0..n]);
copiados += n;
if (tamanho_total > 0) {
const porcento = (copiados * 100) / tamanho_total;
try stdout.print("\rCopiando... {d}% ({d}/{d} bytes)", .{
porcento, copiados, tamanho_total,
});
}
}
try stdout.print("\rCópia concluída: {d} bytes \n", .{copiados});
}
pub fn main() !void {
try copiarComProgresso("arquivo_grande.dat", "arquivo_grande_copia.dat");
}
Copiar para Outro Diretório
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Garantir que o diretório destino existe
std.fs.cwd().makePath("backup/2026") catch |err| {
if (err != error.PathAlreadyExists) return err;
};
// Abrir diretório de destino
var dir_destino = try std.fs.cwd().openDir("backup/2026", .{});
defer dir_destino.close();
// Copiar para o diretório de destino
try std.fs.cwd().copyFile("dados.txt", dir_destino, "dados.txt", .{});
try stdout.print("Arquivo copiado para backup/2026/dados.txt\n", .{});
}
Exemplo Prático: Backup com Timestamp
const std = @import("std");
fn criarBackup(allocator: std.mem.Allocator, arquivo: []const u8) ![]const u8 {
// Obter timestamp
const timestamp = std.time.timestamp();
// Separar nome e extensão
const ponto = std.mem.lastIndexOfScalar(u8, arquivo, '.') orelse arquivo.len;
const nome = arquivo[0..ponto];
const ext = if (ponto < arquivo.len) arquivo[ponto..] else "";
// Criar nome do backup
const backup_nome = try std.fmt.allocPrint(
allocator,
"{s}_{d}{s}",
.{ nome, timestamp, ext },
);
// Copiar
try std.fs.cwd().copyFile(arquivo, std.fs.cwd(), backup_nome, .{});
return backup_nome;
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const backup = try criarBackup(allocator, "config.txt");
defer allocator.free(backup);
try stdout.print("Backup criado: {s}\n", .{backup});
}
Veja Também
- Ler Conteúdo de Arquivo — Leia antes de copiar
- Escrever em Arquivo — Escreva dados durante a cópia
- Verificar se Arquivo Existe — Verifique antes de sobrescrever
- Criar Diretórios — Crie pasta de destino