递归列出文件的例程的奇怪错误

Posted

技术标签:

【中文标题】递归列出文件的例程的奇怪错误【英文标题】:Weird bug with routine to list files recursively 【发布时间】:2013-06-05 14:32:10 【问题描述】:

任何人都可以发现我在这里缺少什么吗?该代码块应该递归访问目录并存储目录路径和其中文件的路径。如果文件是目录,它将 fprintf() 为 true,如果文件不是目录,则为 false。奇怪的是,fileName 的 printf 例程工作正常,但是当将 fprintf fileName 打印到文件时,它只是在应该打印 fileName 的地方打印一个换行符。

/* List the files in "dir_name". */
static void listDir(const char *dirName)

DIR *dir;

/* 
 * Open the directory specified by "dirName". 
 */

dir = opendir(dirName);

/* 
 * Check it was opened. 
 */
if (!dir) 
    fprintf(stderr, "Cannot open directory '%s': %s\n",
            dirName, strerror(errno));
    exit(EXIT_FAILURE);

while (1) 
    struct dirent *entry;
    const char *dir_name;

    /* 
     * "Readdir" gets subsequent entries from "d". 
     */
    entry = readdir(dir);
    if (!entry) 
        /* 
         * There are no more entries in this directory, so break out of the while loop. 
         */
        break;
    
    dir_name = entry->d_name;
    char fileName[PATH_MAX];
            // Assign fileName to path if the file is not a directory
    if (entry->d_type != DT_DIR) 
        if (strcmp(dirName, "/") != 0) 
            snprintf(fileName, PATH_MAX,
                                   "%s/%s", dirName, dir_name);
         else 
            snprintf(fileName, PATH_MAX,
                                   "%s%s", dirName, dir_name);
        
    
    /* Access directory and leave out /. and /.. in the process
     */

    if (entry->d_type == DT_DIR) 

        /* 
         * Check that the directory is not "d" or d's parent. 
         */

        if (strcmp(dir_name, "..") != 0 && strcmp(dir_name, ".") != 0) 
            int path_length;
            char path[PATH_MAX], indexPath[PATH_MAX];
            if (strcmp(dirName, "/") != 0) 
                path_length = snprintf(path, PATH_MAX,
                                       "%s/%s", dirName, dir_name);
             else 
                path_length = snprintf(path, PATH_MAX,
                                       "%s%s", dirName, dir_name);
            
            strcpy(indexPath, path);
            strcat(indexPath, "/masterIndex.db");
            FILE *fp;
            if ((fp = fopen(indexPath, "a")) == NULL) 
                printf("Cannot open file\n");
                return;
            

            printf("File: %s\n      (TRUE)\n", path);
            printf("File: %s\n      (FALSE)\n", fileName); // This routine prints fileName correctly
            fprintf(fp, "%s\n", path);
            fprintf(fp, "%s\n", "true");
            fprintf(fp, "%s\n", fileName); // This routine prints a newline where fileName is supposed to be
            fprintf(fp, "%s\n", "false");
            fclose(fp);

            // Activate this for screw ups
            /*
            char command[PATH_MAX];
            strcpy(command, "cd ");
            strcat(command, path);
            strcat(command, " && rm abc *.finderDB .DS_Store");
            printf("%s\n", command);
            system(command);*/

            if (path_length >= PATH_MAX) 
                fprintf(stderr, "Path length has gotten too long.\n");
                exit(EXIT_FAILURE);
            
            /* 
             * Recursively call "list_dir" with the new path. 
             */
            listDir(path);
        
    

/* 
 * After going through all the entries, close the directory. 
 */
if (closedir(dir)) 
    fprintf(stderr, "Could not close '%s': %s\n",
            dirName, strerror(errno));
    exit(EXIT_FAILURE);


【问题讨论】:

这个函数应该是listDir();?顺便说一句:我没有看到任何对 opendir() 或 closedir() 的调用。请发布真实代码。 刚刚编辑了发布的代码。整个功能块现在就在那里。 ***.com/questions/15068475/…。一个可以帮助您找到 findfirstfile 的示例。 【参考方案1】:

system("cd any_path") 不会对调用过程产生任何影响;改用chdir()..

【讨论】:

系统(“cd path”)在代码中工作正常。如果函数向南并在我的主目录中乱扔索引文件,我只会取消注释该块。感谢 chdir() 的建议。将在以后的代码中使用它。 :) @NaveenMathew system("cd path")“工作正常”,这是真的,但它并没有像你想象的那样做。它启动一个子进程,该进程执行您的 shell 程序,然后解释“cd path”字符串,更改目录,然后退出。它对程序的执行环境没有任何影响(除了浪费一点时间......)。 这个答案在回答 OP 的问题方面没有任何作用,是吗?【参考方案2】:

您在此处缺少初始化fileName

 char fileName[PATH_MAX];

像这样修改这条线:

 char fileName[PATH_MAX] = "";

不这样做可能会导致访问未初始化的变量,即未定义的行为,并可能导致任何或多或少的理性或非理性。

【讨论】:

仍然不工作......它仍然只是打印一个换行符,其中 fileName 应该是...... 我想我成功了。仍然不知道错误是什么,但我只是以另一种方式解决了这个问题。一旦我确定会发布我的代码...【参考方案3】:

这是我设法修复的工作代码。仍然不知道错误是什么,但这应该适用于 POSIX 系统。不确定Windows。感谢 alk 的初始化建议,chidir() 的 xtof(我还没有实现)和 twalberg 解释 chdir() 的作用。

/* List the files in "dir_name". */
static void listDir(const char *dirName)

DIR *dir;

/* 
 * Open the directory specified by "dirName". 
 */

dir = opendir(dirName);

/* 
 * Check it was opened. 
 */
if (!dir) 
    fprintf(stderr, "Cannot open directory '%s': %s\n",
            dirName, strerror(errno));
    exit(EXIT_FAILURE);

while (1) 
    struct dirent *entry;
    const char *dir_name;

    /* 
     * "Readdir" gets subsequent entries from "d". 
     */
    entry = readdir(dir);
    if (!entry) 
        /* 
         * There are no more entries in this directory, so break out of the while loop. 
         */
        break;
    
    dir_name = entry->d_name;

    if (entry->d_type != DT_DIR) 
        char fileName[PATH_MAX] = "", indexPath[PATH_MAX] = "";
        if (strcmp(dirName, "/") != 0) 
            sprintf(fileName, "%s/%s", dirName, dir_name);
         else 
            sprintf(fileName, "%s%s", dirName, dir_name);
        

        strcpy(indexPath, dirName);
        strcat(indexPath, "/masterIndex.db");

        // We don't want to include masterIndex.db in the index list right?
        if (strcmp(indexPath, fileName) != 0) 

            FILE *fp;
            fp = fopen(indexPath, "a");
            if (fp == NULL) 
                printf("Cannot open file\n");
            

            printf("File: %s\n      (FALSE)\n", fileName);
            fprintf(fp, "%s\n", fileName);
            fprintf(fp, "%s\n", "false");
            fclose(fp);
        
    
    /* 
     * See if "entry" is a subdirectory of "dir". 
     */

    if (entry->d_type == DT_DIR) 

        /* 
         * Check that the directory is not "d" or d's parent. 
         */

        if (strcmp(dir_name, "..") != 0 && strcmp(dir_name, ".") != 0
            && strcmp(dir_name, "tmp") != 0
            && strcmp(dir_name, "Jarvis") != 0) 
            int path_length;
            char path[PATH_MAX] = "", indexPath[PATH_MAX] = "";

            if (strcmp(dirName, "/") != 0) 
                path_length = sprintf(path,
                                      "%s/%s", dirName, dir_name);
             else 
                path_length = sprintf(path, "%s%s", dirName, dir_name);
            
            strcpy(indexPath, path);
            strcat(indexPath, "/masterIndex.db");
            FILE *fp;
            fp = fopen(indexPath, "a");
            if (fp == NULL) 
                printf("Cannot open file\n");
            

            printf("File: %s\n      (TRUE)\n", path);
            fprintf(fp, "%s\n", path);
            fprintf(fp, "%s\n", "true");
            fclose(fp);

            // Activate this for screw ups
            /*
               char command[PATH_MAX];
               strcpy(command, "cd ");
               strcat(command, path);
               strcat(command, " && rm abc *.finderDB .DS_Store");
               printf("%s\n", command);
               system(command); */

            if (path_length >= PATH_MAX) 
                fprintf(stderr, "Path length has gotten too long.\n");
                exit(EXIT_FAILURE);
            
            /* 
             * Recursively call "list_dir" with the new path. 
             */
            listDir(path);
        
    

/* 
 * After going through all the entries, close the directory. 
 */
if (closedir(dir)) 
    fprintf(stderr, "Could not close '%s': %s\n",
            dirName, strerror(errno));
    exit(EXIT_FAILURE);


【讨论】:

以上是关于递归列出文件的例程的奇怪错误的主要内容,如果未能解决你的问题,请参考以下文章

递归泛型类型来扩展类型 - 奇怪的行为,这是一个错误吗?

我创建几个c文件,然后直接复制的例程C文件,编译错误Build target 'Target 1' compiling main.c... main

CreateProcess 和奇怪的 nslookup 错误

TRIGGER 语法错误 mysql 说 #1303 - 无法从另一个存储的例程中创建触发器 - phpmyadmin

将例程的内容复制到内存中的另一个位置

从.Net调用访问模块中的例程?