Finding the File Type in Zig
This Zig program is a utility that checks the type of a file system object (file, directory, or symbolic link) specified as a command-line argument. The code begins by importing the standard library (std) and defining the error-propagating main() function. Inside main(), it retrieves the command-line arguments using the std.heap.page_allocator for memory management. A crucial initial step is argument validation: if fewer than two arguments are provided (meaning the user didn’t specify a path), the program prints a “Usage” message, showing its own name (args[0]) and the expected path, before exiting. If a path is present, it’s stored in the path variable (args[1]). The program then attempts to open the specified path using the current working directory (std.fs.cwd().openFile), requesting read-only access, and uses the try keyword to handle any potential opening errors. Following this, the defer file.close() statement is used to guarantee the file handle is closed as soon as the function exits, preventing resource leaks. The core logic involves calling file.stat() to retrieve the metadata (meta) of the file system object. Finally, a switch statement inspects the meta.kind field, which is an enumeration value indicating the object’s type, and prints a descriptive message to the debug output (std.debug.print) stating whether the path refers to a regular file, a directory, a symbolic link, or some other kind of file (else). The entire flow relies on the try operator to gracefully propagate errors that might occur during argument parsing, memory allocation, file opening, or stat retrieval.
const std = @import("std");
pub fn main() !void {
const allocator = std.heap.page_allocator;
const args = try std.process.argsAlloc(allocator);
if (args.len < 2) {
std.debug.print("Usage: {s} <path>\n", .{args[0]});
return;
}
const path = args[1];
var file = try std.fs.cwd().openFile(path, .{ .mode = .read_only });
defer file.close();
const meta = try file.stat(); //<label id="code.ch5.fileDir1"/>
switch (meta.kind) { //<label id="code.ch5.fileDir2"/>
.file => std.debug.print("{s} is a regular file.\n", .{path}),
.directory => std.debug.print("{s} is a directory.\n", .{path}),
.sym_link => std.debug.print("{s} is a symbolic link.\n", .{path}),
else => std.debug.print("{s} is some other kind of file.\n", .{path}),
}
}
Let us see the program in action. Save it as fileType.zig and execute it:
$ zig run fileType.zig -- /bin/ls
/bin/ls is a regular file.
$ zig run fileType.zig -- /bin
/bin is a directory.
Happy coding in Zig!