Efficiently Traverse Directory Tree with opendir(), readdir() and closedir()

后端 未结 5 1067
[愿得一人]
[愿得一人] 2020-12-30 02:35

The C routines opendir(), readdir() and closedir() provide a way for me to traverse a directory structure. However, each dirent structure returned by readdir() does not seem

5条回答
  •  长发绾君心
    2020-12-30 03:02

    Instead of opendir(), you can use a combination of openat(), dirfd() and fdopendir() and construct a recursive function to walk a directory tree:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    void
    dir_recurse (DIR *parent, int level)
    {
        struct dirent *ent;
        DIR *child;
        int fd;
    
        while ((ent = readdir(parent)) != NULL) {
            if ((strcmp(ent->d_name, ".") == 0) ||
                (strcmp(ent->d_name, "..") == 0)) {
                continue;
            }
            if (ent->d_type == DT_DIR) {
                printf("%*s%s/\n", level, "", ent->d_name);
                fd = openat(dirfd(parent), ent->d_name, O_RDONLY | O_DIRECTORY);
                if (fd != -1) {
                    child = fdopendir(fd);
                    dir_recurse(child, level + 1);
                    closedir(child);
                } else {
                    perror("open");
                }
            } else {
                printf("%*s%s\n", level, "", ent->d_name);
            }
        }
    }
    
    int
    main (int argc, char *argv)
    {
        DIR *root;
    
        root = opendir(".");
        dir_recurse(root, 0);
        closedir(root);
    
        return 0;
    }
    

    Here readdir() is still used to get the next directory entry. If the next entry is a directory, then we find the parent directory fd with dirfd() and pass this, along with the child directory name to openat(). The resulting fd refers to the child directory. This is passed to fdopendir() which returns a DIR * pointer for the child directory, which can then be passed to our dir_recurse() where it again will be valid for use with readdir() calls.

    This program recurses over the whole directory tree rooted at .. Entries are printed, indented by 1 space per directory level. Directories are printed with a trailing /.

    On ideone.

提交回复
热议问题