在C(Linux)中通过目录迭代和“存储”文件的最佳方法是什么?

时间:2010-04-23 08:14:24

标签: c linux posix

我编写了一个函数来检查文件是否重复。此功能签名是:

int check_dup_memmap(char *f1_name, char *f2_name)

它返回:

  • ( - 1) - 如果出现问题;
  • (0) - 如果两个文件相似;
  • (+ 1) - 如果两个文件不同;

下一步是编写一个函数,遍历某个目录中的所有文件,应用上一个函数,并提供每个现有重复项的报告。

最初我曾想过编写一个函数来生成一个文件,其中包含某个目录中的所有文件名,然后再次读取该文件并获取并比较每两个文件。这是该函数的一个版本,它获取某个目录中的所有文件名。

void *build_dir_tree(char *dirname, FILE *f)
{
    DIR *cdir = NULL;
    struct dirent *ent = NULL;
    struct stat buf;
    if(f == NULL){
        fprintf(stderr, "NULL file submitted. [build_dir_tree].\n");
        exit(-1);   
    }
    if(dirname == NULL){
        fprintf(stderr, "NULL dirname submitted. [build_dir_tree].\n");
        exit(-1);
    }
    if((cdir = opendir(dirname)) == NULL){
        char emsg[MFILE_LEN];
        sprintf(emsg, "Cannot open dir: %s [build_dir_tree]\t",dirname);
        perror(emsg);
    }
    chdir(dirname);
    while ((ent = readdir(cdir)) != NULL) {
        lstat(ent->d_name, &buf);
        if (S_ISDIR(buf.st_mode)) {
            if (strcmp(".", ent->d_name) == 0 ||
                    strcmp("..", ent->d_name) == 0) {
                continue;
            }
            build_dir_tree(ent->d_name, f);
        }
        else{
            fprintf(f, "/%s/%s\n",util_get_cwd(),ent->d_name);
        }
    }
    chdir("..");
    closedir(cdir);
}

我仍然认为这种方法效率不高,因为我必须一次又一次地解析文件。

在您看来,我应该遵循哪些其他方法:

  • 编写数据结构并保存文件而不是将其写入文件中?我认为对于包含大量文件的目录,内存将变得非常分散。
  • 将所有文件名保存在自动扩展数组中,以便我可以通过索引轻松访问每个文件,因为它们将位于连续的内存位置。
  • 使用mmap()将此文件映射到内存中?但是,随着文件变大,mmap可能会失败。

对此有任何意见。我想选择最有效的路径,并尽可能少地访问资源。这是该计划的要求......

编辑: 有没有办法获取某个目录中的文件数量,而无需迭代它?

1 个答案:

答案 0 :(得分:3)

您可能想要使用哈希或校验和;创建每个文件内容的哈希值,并将每个哈希值与该哈希值的文件名列表相关联。然后,当您构造哈希时,您将看到其他文件也共享相同的哈希。只有当你遇到碰撞时,你才真正必须比较完整的文件。如果你选择一个好的哈希函数,那么碰撞应该是相对罕见的,使得完全比较很少。

请注意,哈希的大小和冲突的数量之间存在权衡;如果你使用较小的哈希,冲突可能会更频繁,但你会减少每个文件的空间,如果你使用更大的哈希,那么你将不得不做更少的完整文件比较,但需要保持和比较较大的哈希值。此外,一些散列函数导致的冲突比其他散列更少,但有些更好的散列函数可能比较差的散列函数更耗时且计算密集。

文件和目录遍历的有效方法是使用ftwnftw