File Tree Walk
2025-03-04, Tue
Nontrivial program that processes a bunch of files typically involves
traversal of a directory recursively. (Un)Surprisingly, there is the
ftw
set of library functions dedicated to this job.
Since ftw(3)
is deprecated by nftw(3)
according to the
standard1. It's the later one that will be talked
about here. A simple example that prints out all files recursively in
a directory is listed below:
#include <ftw.h> /* for nftw */ #include <stdio.h> /* for stdout, stderr and fprintf */ #include <stdlib.h> /* for exit(3) */ #include <errno.h> /* for errno */ #include <string.h> /* for strerror */ int proc_fun(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { fprintf(stdout, "%s\n", fpath); return 0; } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stdout, "usage: %s <directory>\n", argv[0]); exit(0); } if (nftw(argv[1], proc_fun, 1, 0)) { fprintf(stderr, "unable to handle \"%s\": %s\n", argv[1], strerror(errno)); exit(errno); } return 0; }
A while ago I wrote a script in JavaScript to do the similar task. With the API provided by Node.js, the snippet looks like this:
import * as fs from 'node:fs/promises'; import path from 'nod:path'; async function walkDirectory(dir, procFun = console.log) { const files = await fs.readdir(dir); for(const name of files) { const filePath = path.resolve(dir, name); const stat = await fs.stat(filePath); if (stat.isFile()) { await procFun(filePath); } else if (stat.isDirectory()) { await walkDirectory(filePath, procFun); } else { throw 'unknown type'; } } }
As for Emacs Lisp
, it provides directory-files-recursively
to achieve
the same goal.
Footnotes:
Or should I say, moved to obsolescent status?
Likewise, should fdw
be called file tree traversal
? The verbiage
difference among documentation of different Unix distros span from
annoyance to confusion: IBM z/OS calls the same function "Traverse a
file tree", while Oracle Solaris calls it "walk a file tree", and
macOS calls it "traverse (walk) a file tree". You gotta be kidding me.