代码之家  ›  专栏  ›  技术社区  ›  tpar44

使用fts遍历文件系统(3)

  •  2
  • tpar44  · 技术社区  · 14 年前

    我有个问题 fts(3) 。每当我尝试访问 fts_children() 作用当我在 http://www.kernel.org/doc/man-pages/online/pages/man3/fts.3.html 它声称在read函数运行并返回通过 link 结构中的字段。我怀疑child_function没有返回任何内容,但我觉得这与手册页不符。我是否应该将这些文件添加到子缓冲区,因为我认为这是自动完成的?我的代码如下, 谢谢

    #include<stdlib.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fts.h>
    #include<string.h>
    
    int compare (const FTSENT**, const FTSENT**);
    
    int main(int argc, char* const argv[])
    {
    
            FTS* file_system = NULL;
            FTSENT* child = NULL;
            FTSENT* parent = NULL;
            FTSENT* temp = NULL;
    
            file_system = fts_open(argv + 1,FTS_COMFOLLOW | FTS_NOCHDIR,&compare);
    
            while( (parent = fts_read(file_system)) != NULL)
            {
    
                 child = fts_children(file_system,0);
                 printf("%s\n", child->fts_path);
    
    
            }
    //      while (child ->fts_link != NULL)
          //         child = child->fts_link;
            fts_close(file_system);
            return 0;
    }
    
    int compare(const FTSENT** one, const FTSENT** two){
            return (strcmp((*one)->fts_name, (*two)->fts_name));
    }
    "test_fs.c" 43L, 1108C  
    
    2 回复  |  直到 14 年前
        1
  •  9
  •   Mr. Curious    12 年前

    如果您只对遍历指定路径的所有目录和文件感兴趣,只需重复调用 fts_read 。

    如果您只想遍历流,@sehe的示例可以重写为:

    #include<stdlib.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<fts.h>
    #include<string.h>
    #include<errno.h>
    
    int compare (const FTSENT**, const FTSENT**);
    void indent (int i);
    
    int main(int argc, char* const argv[])
    {
        FTS* file_system = NULL;
        FTSENT *node,    = NULL;
    
        if (argc<2)
        {
            printf("Usage: %s <path-spec>\n", argv[0]);
            exit(255);
        }
    
        file_system = fts_open(argv + 1,FTS_COMFOLLOW|FTS_NOCHDIR,&compare);
    
        if (NULL != file_system)
        {
            while( (node = fts_read(file_system)) != NULL)
            {
                switch (node->fts_info) 
                {
                    case FTS_D :
                    case FTS_F :
                    case FTS_SL:
                        indent(node->fts_level);
                        printf("%s\n", node->fts_name);
                        break;
                    default:
                        break;
                }
            }
            fts_close(file_system);
        }
        return 0;
    }
    
    int compare(const FTSENT** one, const FTSENT** two)
    {
        return (strcmp((*one)->fts_name, (*two)->fts_name));
    }
    
    void indent(int i)
    {
        for (; i > 0; i--) 
            printf("    ");
    }
    

    当您运行它时,它会遍历流,并按顺序列出所有文件和目录:

    ★ mkdir -p test/A/1 test/A/2 test/B/1 test/B/2
    
    ★ tree test                                   
    test
    ├── A
    │   ├── 1
    │   └── 2
    └── B
        ├── 1
        └── 2
    
    ★ ./fts test                                  
    test
        A
            1
            2
        B
            1
            2
    

    呼叫 fts_children 仅当您想要特定目录的子节点列表时。那样的话,你必须打电话 fts读取 打电话前至少一次 fts儿童 ;否则 fts儿童 将只返回中指定的节点 argv 参数到 fts_open 。

        2
  •  2
  •   sehe    14 年前

    您只需要添加一个NULL检查。

    你可能想

    • 为添加一个 file_system
    • 检查命令行参数
    • 添加更多错误处理:

      这个 fts_children() 函数返回一个指向 FTSENT 描述中第一个条目的结构 NULL 如果成功,则终止目录中文件的链接列表。这个 fts_children() 功能可能会失败并设置 errno 对于 chdir() , malloc() , opendir() , readdir() 和 stat() 函数指定。

    使现代化 对于评论中的新问题:

    • 链表遍历的while循环放错了位置(在外循环之外?)
    • printf只显示了路径。。。而不是文件名。

    当你在做的时候:

    #include<stdlib.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fts.h>
    #include<string.h>
    #include<errno.h>
    
    int compare (const FTSENT**, const FTSENT**);
    
    int main(int argc, char* const argv[])
    {
        FTS* file_system = NULL;
        FTSENT* child = NULL;
        FTSENT* parent = NULL;
    
        if (argc<2)
        {
            printf("Usage: %s <path-spec>\n", argv[0]);
            exit(255);
        }
    
        file_system = fts_open(argv + 1,FTS_COMFOLLOW | FTS_NOCHDIR,&compare);
    
        if (NULL != file_system)
        {
            while( (parent = fts_read(file_system)) != NULL)
            {
                child = fts_children(file_system,0);
    
                if (errno != 0)
                {
                    perror("fts_children");
                }
    
                while ((NULL != child)
                    && (NULL != child->fts_link))
                {
                    child = child->fts_link;
                    printf("%s%s\n", child->fts_path, child->fts_name);
                }
            }
            fts_close(file_system);
        }
        return 0;
    }
    
    int compare(const FTSENT** one, const FTSENT** two)
    {
        return (strcmp((*one)->fts_name, (*two)->fts_name));
    }
    

    样本输出片段:

    ./.profiles/sehe/.opera/icons/cache/g_0000
    ./.profiles/sehe/.opera/icons/cache/g_0000/opr00002.tmp
    ./.profiles/sehe/.opera/icons/cache/g_0000/opr00003.tmp
    ./.profiles/sehe/home/sehe/.mozilla
    fts_children: Permission denied
    ./.vbox-sehe-ipc/lock