Search code examples
clinuxnftw

using nftw to only traverse the folder specified


I am using nftw() to do directory traversal. Right now I am only wanting to list out all the files in the directory specified, however it seems to no matter what go down all the folders. It seems that nftw still traverses even if I specify FTW_PHYS.

The only work around is setting up

if (ftwbuf->level > 1) {
    return;
}

in the function that gets called. However it is still calling this function on all of these directories.


Solution

    1. Enable GNU Source before any include directives.
    #define _GNU_SOURCE
    
    1. Before calling nftw() enable FTW_ACTIONRETVAL in the flags. This enables nftw() to recourse its execution based on return values from callback_function().
    /* snippet from nftw manpage */
    #define MAX_OPEN_FDS    64
        flags |= FTW_ACTIONRETVAL; // enables callback_function() to recourse 
        if (nftw ((argc < 2) ? "." : argv[1], callback_function, MAX_OPEN_FDS, flags)
                == -1) {
            perror ("nftw");
            exit (EXIT_FAILURE);
        }
    
    1. In the callback_function() at the beginning itself skip the directory if it's above desired level.
    #define DEPTH_LIMIT 1
    /*
    ...
    */
    int
    callback_function (const char *fpath, const struct stat *sb,
                  int tflag, struct FTW *ftwbuf) {
    // works even when FTW_DEPTH is enabled.
    // at the top first condition to check; 
    if (ftwbuf->level > DEPTH_LIMIT) return FTW_SKIP_SIBLINGS;
    /*
    ...
    */
        return FTW_CONTINUE;
    }
    
    1. Whenever nftw() returns with a file in a directory crossing the DEPTH_LIMIT, FTW_SKIP_SIBLINGS instructs it to skip that directory and continue with siblings in parent directory.

    2. If you omit FTW_DEPTH in nftw() flags, you can use FTW_SKIP_SUBTREE feature; where nftw() skips a directory right away.

      • FTW_DEPTH instructs nftw() to pass the directory itself after going through all files & sub-directories in it. This post-order traversal of directories makes it difficult to use FTW_SKIP_SUBTREE;
    // without `FTW_DEPTH` in nftw-flags 
    int
    callback_function (const char *fpath, const struct stat *sb,
                  int tflag, struct FTW *ftwbuf) {
    /*
    ...
    */
        if (DEPTH_LIMIT == ftwbuf->level && FTW_D == tflag) // a directory
            return FTW_SKIP_SUBTREE; // don't get into the directory
        else
            return FTW_CONTINUE;
    }