Like file paths, Hare has good support for working with directories.
use io;
use fmt;
use fs;
use strings;
use os;
// walkfunc defines a callback we will run for every directory entry we
// see so the caller can use it.
type walkfunc = fn(dir: str, entry: fs::dirent) void;
// walk takes a root directory and a callback function and will traverse
// down into each sub-directory it finds while also calling the callback
// with each directory entry.
fn walk(dir: str, cb: *walkfunc) (void | fs::error | nomem) = {
const entries = os::readdir(dir)?;
defer fs::dirents_free(entries);
for (let entry .. entries) {
cb(dir, entry);
if (fs::isdir(entry.ftype)) {
const sub = strings::concat(dir, "/",
entry.name)!;
walk(sub, cb)?;
};
};
};
// walkcb is our specified walkfunc we want to execute for each
// directory entry.
fn walkcb(dir: str, entry: fs::dirent) void = {
const path = strings::concat(dir, "/", entry.name)!;
defer free(path);
fmt::printf("WALK - path: {}, file: {}, dir: {}\n", path,
fs::isfile(entry.ftype),
fs::isdir(entry.ftype))!;
};
export fn main() void = {
// We can make a directory and defer deleting it when we're
// finished.
os::mkdir("/tmp/new-dir", 0o755)!;
defer os::rmdirall("/tmp/new-dir")!;
// Lets make some more sub-directories to create some hierarchy.
os::mkdir("/tmp/new-dir/sub1", 0o755)!;
os::mkdir("/tmp/new-dir/sub2", 0o755)!;
// Now we can add some files inside of each of the directories.
const f1 = os::create("/tmp/new-dir/file.txt", 0o644)!;
defer io::close(f1)!;
const f1 = os::create("/tmp/new-dir/sub1/cool.txt", 0o644)!;
defer io::close(f1)!;
const f1 = os::create("/tmp/new-dir/sub2/l33t.txt", 0o644)!;
defer io::close(f1)!;
// We can open the directory we created and get the entries
// inside of it and check whether they are files or directories.
const entries = os::readdir("/tmp/new-dir")!;
defer fs::dirents_free(entries);
for (let entry .. entries) {
fmt::printf("name: {}, file: {}, dir: {}\n", entry.name,
fs::isfile(entry.ftype),
fs::isdir(entry.ftype))!;
};
// Hare does not have built-in support for walking a directory
// at a specified root, but we can implement a basic version of
// this ourselves. You may also consider using an iterator for
// more a efficient method.
walk("/tmp/new-dir", &walkcb)!;
};
Back to table of contents