Originally Posted by
nime
This is very simple but efficient and potrable code for recursive directory scanning for c files which will work in most "normal" cases...
What on earth makes you think it is more portable than nftw()? Both nftw() and opendir() et al. are standardized in POSIX.1-2001. Granted, on some SVr4 systems you'd have to use ftw() instead, but POSIX.1-2008 obsoletes ftw(), which makes nftw() better for future use.
Your code will get confused if directories or files are renamed, created, or deleted (in the same directory or in a parent directory) while scanning. In most cases, those do not bother nftw() at all.
nftw() even detects loops (circular symlinks), and should report each file only once (even if renamed). Your code assumes that FILENAME_MAX is the maximum length for a path, but in reality, it's just the maximum length for one file name, i.e. one path component.
Why don't you try to compile and run the following program using gcc in Windows, and see for yourself? I don't have or use Windows myself, but if opendir() works -- it's not in microsoft's C libraries, so you are using something else anyway --, then nftw() should work too.
Code:
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 500
#include <stdlib.h>
#include <ftw.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int check(const char *const path, const struct stat *const info, int const typeflag, struct FTW *const ftwbuf)
{
/* Only consider regular files */
if (typeflag == FTW_F) {
const char *const name = path + ftwbuf->base;
const int depth = ftwbuf->level;
const char *const extension = strrchr(name, '.');
/* Only consider files with extension .c */
if (extension && !strcmp(extension, ".c")) {
/* Print depth, size in kilobytes (units of 1024 bytes), and full path. */
printf("%3d %9.0fk %s\n", depth, (double)info->st_size / 1024.0, path);
}
}
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "/?")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help | /? ]\n", argv[0]);
fprintf(stderr, " %s DIRECTORY\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This program will list all .c files under DIRECTORY.\n");
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
if (nftw(argv[1], check, FOPEN_MAX - 1, 0)) {
fprintf(stderr, "Aborted (%s).\n", strerror(errno));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}