finddup
Borland C++ Compiler 5.5
finddup.cpp
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 1000000 #define READ_FIRST 16384 // 型定義 typedef unsigned long u_long; typedef struct { // ファイル情報構造体 std::string strPath; int iDupFlag; // 重複フラグ } SFileInfo; typedef std::multimap
MMapULongFI; // グローバル変数 static MMapULongFI g_mmap; // プロトタイプ宣言 int files(const char *pcDir); int filecmp(const char *pcFile1, const char *pcFile2); int main(int argc, char **argv) { MMapULongFI::iterator pmmap; MMapULongFI::iterator pmmapTarget; SFileInfo *pfi; SFileInfo *pfiTarget; char acDir[_MAX_DIR]; int iDirLen; int iCount; int i; if (argc < 2) { fprintf(stderr, "usage: finddup dir [...]\n"); return 1; } for (i = 1; i < argc; i++) { iDirLen = strlen(argv[i]); if (_MAX_DIR <= iDirLen) { fprintf(stderr, "error: dir too long\n"); return 1; } strcpy(acDir, argv[i]); if (0 < iDirLen && _mbsrchr(acDir, '\\') == acDir + iDirLen - 1) { acDir[iDirLen - 1] = '\0'; } if (files(acDir) != 0) { return 1; } } for (pmmap = g_mmap.begin(); pmmap != g_mmap.end(); pmmap++) { pfi = &(pmmap->second); if (pfi->iDupFlag != 0) { continue; } iCount = 0; for (pmmapTarget = pmmap; ++pmmapTarget != g_mmap.end(); ) { if (pmmapTarget->first != pmmap->first) { break; } pfiTarget = &(pmmapTarget->second); if (pfiTarget->iDupFlag != 0) { continue; } if (filecmp(pfiTarget->strPath.c_str(), pfi->strPath.c_str()) == 0) { pfiTarget->iDupFlag = 1; if (iCount == 0) { printf("\n%u KB (%u B)\n", (pmmap->first + 1023) / 1024, pmmap->first); printf("%s\n", pfi->strPath.c_str()); } printf("%s\n", pfiTarget->strPath.c_str()); iCount++; } } } return 0; } int files(const char *pcDir) { struct _finddata_t fd; SFileInfo fi; char acPath[_MAX_PATH]; long lHandle; int iDirLen; fi.iDupFlag = 0; iDirLen = strlen(pcDir); sprintf(acPath, "%s\\*.*", pcDir); lHandle = _findfirst(acPath, &fd); if (lHandle == -1) { fprintf(stderr, "error: _findfirst(%s)\n", acPath); return -1; } do { if (fd.attrib & _A_SUBDIR) { if (strcmp(fd.name, ".") && strcmp(fd.name, "..")) { if (_MAX_DIR <= iDirLen + 1 + strlen(fd.name)) { fprintf(stderr, "error: dir too long\n"); return -1; } sprintf(acPath, "%s\\%s", pcDir, fd.name); files(acPath); } } else { if (_MAX_PATH <= iDirLen + 1 + strlen(fd.name)) { fprintf(stderr, "error: path too long\n"); fprintf(stderr, "[%s]\n[%s]\n", pcDir, fd.name); } else { sprintf(acPath, "%s\\%s", pcDir, fd.name); fi.strPath = acPath; g_mmap.insert(MMapULongFI::value_type(fd.size, fi)); } } } while (_findnext(lHandle, &fd) == 0); _findclose(lHandle); return 0; } int filecmp(const char *pcFile1, const char *pcFile2) { static char acBuf1[BUFFER_SIZE]; static char acBuf2[BUFFER_SIZE]; FILE *pfile1; FILE *pfile2; int iReadCount; int iRead1; int iRead2; int iRetVal; u_long ulCount; pfile1 = fopen(pcFile1, "rb"); if (pfile1 == NULL) { fprintf(stderr, "error: fopen(%s)\n", pcFile1); return -1; } pfile2 = fopen(pcFile2, "rb"); if (pfile2 == NULL) { fprintf(stderr, "error: fopen(%s)\n", pcFile2); fclose(pfile1); return -1; } ulCount = 0; for (iReadCount = READ_FIRST; ; iReadCount = BUFFER_SIZE) { iRead1 = fread(acBuf1, sizeof(char), iReadCount, pfile1); iRead2 = fread(acBuf2, sizeof(char), iReadCount, pfile2); if (iRead1 != iRead2) { iRetVal = 1; break; } if (memcmp(acBuf1, acBuf2, iRead1) != 0) { if (iReadCount != READ_FIRST) { // fprintf(stderr, "\n%u\n[%s]\n[%s]\n", ulCount, pcFile1, pcFile2); } iRetVal = 1; break; } if (iRead1 != iReadCount) { iRetVal = 0; break; } ulCount += iReadCount; } fclose(pfile2); fclose(pfile1); return iRetVal; }