如何比较获得两个文件夹下不相同文件的目录

在两台电脑上分别有两个工程文件夹,分别有三千多和两千多的文件。现在需要比对两个文件夹下所有文件(及子目录下的所有文件)是否相同(指内容,也就是需要用到SHA256或MD5等哈希算法),并将不相同的文件的文件绝对路径输出。
由于是在两台不同的电脑上,所以可以通过在第一台电脑上运行并记录下文件路径与哈希值的对应,并在第二台电脑上再次运行,进行比对。

使用了ChatGPT写了部分代码,但进行一些测试后发现,获取文件目录和哈希算法这两个函数均无法运行。

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_DEPRECATE

#include <cstdlib>
#include "dirent.h"
#include <fstream>
#include <io.h>
#include <iostream>
#include <openssl/sha.h> // 引入openssl库
#include <string>
#include <windows.h>

using namespace std;

const int MAX_FILE_NAME_LENGTH = 1024; //定义最大文件名长度

//#define ERROR = -1;
/* 返回值表
 * -1 文件打开错误
 * -2 文件读取错误
 */

int GetSHA256(string directory, char** SHA256s, int serial)
{
    ifstream file(directory, ios::binary); // 以二进制方式打开大文件
    if (!file)
    {
        cerr << "File open error!" << endl;
        return -1;
    }

    // 初始化SHA256上下文
    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    char buffer[1024];
    while (file.read(buffer, sizeof(buffer)))   // 逐块读取文件内容
    {
        SHA256_Update(&ctx, buffer, file.gcount()); // 更新SHA256上下文
    }

    if (!file.eof())    // 读取文件出错
    {
        cerr << "File read error!" << endl;
        return -2;
    }

    // 计算SHA256值
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_Final(hash, &ctx);

    // 保存SHA256值
    memcpy(SHA256s[serial], hash, 32);

    file.close(); // 关闭文件
    return 0;
}

void GetAllFiles(string path, string* files, int& count) 
{
    DIR* pDir;
    dirent* pEnt;
    pDir = opendir(path.c_str());   //打开指定的目录
    while (pEnt = readdir(pDir))    //读取目录下的每一项
    {
        if (strcmp(pEnt->d_name, ".") == 0 || strcmp(pEnt->d_name, "..") == 0)
        {
            continue;
            // .和..是Linux系统默认的当前目录和父级目录,需排除
        }
        string absPath = path + "/" + pEnt->d_name;
        if (pEnt->d_type == DT_DIR)
        {   //判断是否为目录
            GetAllFiles(absPath, files, count);
            //递归扫描子目录
        }
        else
        {
            files[count] = absPath;   //将绝对路径保存到数组中
            count++;
        }
    }
    closedir(pDir);   //关闭目录
}

int main()
{
    const char* directory_of_root;
    scanf("%[^\n]", directory_of_root);
    string* directory_of_files = new string;
    int fileCount = 0;

    GetAllFiles(directory_of_root, directory_of_files, fileCount);

    return 0;
}

该回答引用GPT
针对代码中存在的问题进行说明和解决:

头文件"dirent.h"在部分操作系统中可能不存在,需要手动进行安装配置,并且在部分情况下可能需要使用<dirent.h>。

函数GetSHA256中的参数"char** SHA256s"应该改为"unsigned char* SHA256s",由于SHA256值是unsigned char类型的,不适用于char类型。

函数GetAllFiles中的参数"string* files"应该改为"string files[]",由于数组无法动态生成大小,因此需要在函数前将大小固定,并在函数内部进行赋值。

在文件头部添加了一些预编译指令,但是需要注意这些指令的使用场景和平台差异性。

在主函数中,需要使用"new string[]"进行动态数组的分配,否则会出现内存错误。

在主函数内部,需要遍历所有文件并计算SHA256值,在遍历时需要使用循环进行逐个计算,并将文件路径和SHA256值保存到相应的数组中。

修改后的代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <openssl/sha.h>
#include <string>

using namespace std;

const int MAX_FILE_NAME_LENGTH = 1024;

int GetSHA256(string directory, unsigned char *SHA256s) {
  ifstream file(directory, ios::binary);
  if (!file) {
    cerr << "File open error!" << endl;
    return -1;
  }

  SHA256_CTX ctx;
  SHA256_Init(&ctx);

  char buffer[1024];
  while (file.read(buffer, sizeof(buffer))) {
    SHA256_Update(&ctx, buffer, file.gcount());
  }

  if (!file.eof()) {
    cerr << "File read error!" << endl;
    return -2;
  }

  unsigned char hash[SHA256_DIGEST_LENGTH];
  SHA256_Final(hash, &ctx);

  memcpy(SHA256s, hash, SHA256_DIGEST_LENGTH);

  file.close();
  return 0;
}

void GetAllFiles(string path, string files[], int &count) {
  DIR *pDir;
  dirent *pEnt;
  pDir = opendir(path.c_str());
  while ((pEnt = readdir(pDir)) != NULL) {
    if (strcmp(pEnt->d_name, ".") == 0 || strcmp(pEnt->d_name, "..") == 0) {
      continue;
    }
    string absPath = path + "/" + pEnt->d_name;
    if (pEnt->d_type == DT_DIR) {
      GetAllFiles(absPath, files, count);
    } else {
      files[count] = absPath;
      count++;
    }
  }
  closedir(pDir);
}

int main() {
  char directory_of_root[MAX_FILE_NAME_LENGTH];
  fgets(directory_of_root, MAX_FILE_NAME_LENGTH, stdin);
  directory_of_root[strlen(directory_of_root) - 1] = '\0';

  int max_files = 5000;
  string *directory_of_files = new string[max_files];
  unsigned char *SHA256_values = new unsigned char[max_files * SHA256_DIGEST_LENGTH];
  int fileCount = 0;

  GetAllFiles(directory_of_root, directory_of_files, fileCount);

  for (int i = 0; i < fileCount; i++) {
    string current_file = directory_of_files[i];
    unsigned char *current_hash = SHA256_values + i * SHA256_DIGEST_LENGTH;
    GetSHA256(current_file, current_hash);
  }

  delete[] directory_of_files;
  delete[] SHA256_values;

  return 0;
}