C语言实现文件夹内相同内容文件分组
C语言实现文件夹内相同内容文件分组
本文介绍使用 C 语言编写程序,遍历指定文件夹,找出其中内容完全相同的文件并进行分组。
实现思路
- 遍历指定文件夹,获取所有文件路径。
- 对于每个文件,计算它的哈希值(可以使用 MD5 或 SHA1 等算法),并将哈希值作为键,文件路径作为值存入一个哈希表中。
- 遍历哈希表,对于每个键值对,如果键对应的值的数量大于 1,则说明有多个文件的内容相同,将它们分为一组。
- 输出每组文件的路径。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <openssl/md5.h>
#define MAX_PATH 1024
#define HASH_SIZE 1024
typedef struct node {
char *path;
struct node *next;
} Node;
Node *hash_table[HASH_SIZE];
void add_to_hash_table(char *path) {
FILE *fp = fopen(path, 'rb');
if (fp == NULL) {
perror('fopen');
return;
}
unsigned char md5[MD5_DIGEST_LENGTH];
MD5_CTX ctx;
MD5_Init(&ctx);
char buf[1024];
int len;
while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
MD5_Update(&ctx, buf, len);
}
MD5_Final(md5, &ctx);
fclose(fp);
char key[MD5_DIGEST_LENGTH * 2 + 1];
for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
sprintf(key + i * 2, '%02x', md5[i]);
}
key[MD5_DIGEST_LENGTH * 2] = '\0';
int index = 0;
for (int i = 0; i < strlen(key); i++) {
index = (index * 31 + key[i]) % HASH_SIZE;
}
Node *p = hash_table[index];
while (p != NULL) {
if (strcmp(p->path, path) == 0) {
return;
}
p = p->next;
}
Node *node = malloc(sizeof(Node));
node->path = strdup(path);
node->next = hash_table[index];
hash_table[index] = node;
}
void traverse_dir(char *dir) {
DIR *dp = opendir(dir);
if (dp == NULL) {
perror('opendir');
return;
}
struct dirent *entry;
char path[MAX_PATH];
while ((entry = readdir(dp)) != NULL) {
if (strcmp(entry->d_name, '.') == 0 || strcmp(entry->d_name, '..') == 0) {
continue;
}
snprintf(path, sizeof(path), '%s/%s', dir, entry->d_name);
if (entry->d_type == DT_DIR) {
traverse_dir(path);
} else if (entry->d_type == DT_REG) {
add_to_hash_table(path);
}
}
closedir(dp);
}
void print_groups() {
for (int i = 0; i < HASH_SIZE; i++) {
Node *p = hash_table[i];
if (p == NULL) {
continue;
}
printf('Group:\n');
while (p != NULL) {
printf(' %s\n', p->path);
p = p->next;
}
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, 'Usage: %s dir\n', argv[0]);
exit(1);
}
memset(hash_table, 0, sizeof(hash_table));
traverse_dir(argv[1]);
print_groups();
return 0;
}
使用方法
- 编译:
gcc -o find-duplicate-files find-duplicate-files.c -lcrypto
- 运行:
./find-duplicate-files dir
其中,dir是要遍历的文件夹路径。
注意:
- 该程序需要使用 OpenSSL 库,请确保已安装 OpenSSL 库。
- 由于哈希表的大小固定,如果文件数量非常多,可能会出现哈希冲突,导致程序无法正确识别相同内容的文件。可以尝试增大
HASH_SIZE的值来减少哈希冲突的概率。 - 该程序只比较文件内容,不考虑文件属性(如修改时间、权限等)。
原文地址: https://www.cveoy.top/t/topic/lfdq 著作权归作者所有。请勿转载和采集!