Is there a way to cp -r
with Zig’s stdlib? I see there’s Dir.deleteTree
, but I don’t see anything for copying.
https://ziglang.org/documentation/master/std/#A;std?fs%20copy
It doesn’t seem there’s anything particularly interesting in fs
. Maybe there’s a related syscall that just hasn’t been wired into the high-level interface?
https://ziglang.org/documentation/master/std/#A;std?os%20copy
Nope, nothing interesting under os
either.
I guess the first question is whether the OS gives us a good tool for the job or if we would have to implement everything ourselves.
Looking at a cp -r
strace it seems that it’s entirely up to us to implement this functionality though.
So, I guess a PR would be welcome :^)
A basic/naive approach (with no special handling of the dest existing, metadata copying, etc) would be:
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
var src_dir = try std.fs.cwd().openIterableDir("src_dir", .{});
defer src_dir.close();
var dest_dir = try std.fs.cwd().makeOpenPath("dest_dir", .{});
defer dest_dir.close();
var walker = try src_dir.walk(allocator);
defer walker.deinit();
while (try walker.next()) |entry| {
switch (entry.kind) {
.file => {
try entry.dir.copyFile(entry.basename, dest_dir, entry.path, .{});
},
.directory => {
try dest_dir.makeDir(entry.path);
},
else => return error.UnexpectedEntryKind,
}
}
}
Out of curiosity, I benchmarked it on Windows against xcopy
using a giant nested directory (the result of npx create-react-app my-app
) and the Zig version loses, so there’s potential for optimization:
> hyperfine "xcopy /E /Q /I /Y my-app my-app-copy" "copydir.exe" --prepare="rm -rf my-app-copy"
Benchmark 1: xcopy /E /Q /I /Y my-app my-app-copy
Time (mean ± σ): 23.462 s ± 0.625 s [User: 1.557 s, System: 19.337 s]
Range (min … max): 22.704 s … 24.793 s 10 runs
Benchmark 2: copydir.exe
Time (mean ± σ): 27.017 s ± 0.307 s [User: 1.063 s, System: 24.863 s]
Range (min … max): 26.502 s … 27.508 s 10 runs
Summary
'xcopy /E /Q /I /Y my-app my-app-copy' ran
1.15 ± 0.03 times faster than 'copydir.exe'
(similar results with the c_allocator
, so it’s not the GPA that’s causing the difference)