Search code examples
cnftw

C: Specify maximum depth of search using nftw


In C, is there a way to specify the maximum depth from the base directory that nftw will search? For example, say the directory dir that I want to search has a sub-subdirectory, but I only want nftw to search through subdir and not sub-subdir, or anything below that.

dir
 \_ subdir
    |__ file1
    |__ file2
     \_ sub-subdir
        |__ file1
        |__ file2
         \_ file3

Solution

  • According to the manual page (http://man7.org/linux/man-pages/man3/nftw.3.html) you can stop to go in subdirectories from inside the function argument.

    From the example reported in the manual with a limitation to 2 levels in subdirs the source code is:

    #define _XOPEN_SOURCE 500
    #include <ftw.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    
    
    // max num of sub dirs
    #define MAXLEVEL  2
    
    static int display_info(const char *fpath, const struct stat *sb,
                int tflag, struct FTW *ftwbuf)
    {
       // if the depth is above the max sub dirs, continue to next file
       if (ftwbuf->level > MAXLEVEL) {
           return 0; 
       }
       printf("%-3s %2d %7jd   %-40s %d %s\n",
           (tflag == FTW_D) ?   "d"   : (tflag == FTW_DNR) ? "dnr" :
           (tflag == FTW_DP) ?  "dp"  : (tflag == FTW_F) ?   "f" :
           (tflag == FTW_NS) ?  "ns"  : (tflag == FTW_SL) ?  "sl" :
           (tflag == FTW_SLN) ? "sln" : "???",
           ftwbuf->level, (intmax_t) sb->st_size,
           fpath, ftwbuf->base, fpath + ftwbuf->base);
       return 0;           /* To tell nftw() to continue */
    }
    
    int main(int argc, char *argv[])
    {
       int flags = 0;
    
       if (argc > 2 && strchr(argv[2], 'd') != NULL)
           flags |= FTW_DEPTH;
       if (argc > 2 && strchr(argv[2], 'p') != NULL)
           flags |= FTW_PHYS;
    
       if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1) {
           perror("nftw");
           exit(EXIT_FAILURE);
       }
       exit(EXIT_SUCCESS);
    }