[C/C++][文件操作]目录/文件夹对比并列出同名较新文件、较旧文件 V1

Cplusplus
头像
523066680
Administrator
Administrator
帖子: 347
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 31 times
Been thanked: 31 times
联系:

[C/C++][文件操作]目录/文件夹对比并列出同名较新文件、较旧文件 V1

帖子 #1 523066680 » 2016年07月23日 12:08

主要是模仿robocopy的部分功能

(robocopy /L 参数可以列出本地目录和备份目录中的异同之处,主要是标记出:较新的、较旧的、多出的文件 )
现在还不会写GUI,打算后面自己做目录树diff,可以手动点选要复制的文件。
同时我也知道有现成的软件,比如meld,但是windows下面不太好用。

特性:
一、支持Unicode字符路径
二、使用了WriteConsoleW函数屏幕输出以保留Unicode字符完整性
(虽然终端上有些Unicode字符看不到,但是标记、粘贴到别的编辑器上面是完整的,至少不会变成问好)
如果是用 wprintf 或者转GBK再printf,则Unicode字符会丢失。
三、判断为当前输出为重定向时,切换到WriteFile函数输出到指定的文件。这一点是因为WriteConsoleW
输出的信息不支持直接重定向,好在conio.h提供了判断输出环境的方法。

这里感谢 flyue 在"终端输出Unicode字符、重定向、标记复制" 方面的指教

编译备注:为了方便Unicode模式,用了 wmain做入口函数,使用mingw g++编译时,加上 -municode 参数,
否则会提示 winMain 未定义。在stackoverflow看到的解决方法。
本来vc的 cl.exe 也可以直接编译,但是居然默认不带dirent.h ... windows有另外一套API,也罢
等我学会了再写一个API的版本。

Code: [全选] [展开/收缩] [Download] (Untitled.cpp)
  1. /*
  2.    g++ CompareW.cpp -municode -o CompareW
  3. */
  4.  
  5. #include <cstdio>
  6. #include <cstdlib>
  7. #include <cwchar>
  8. #include <cstring>
  9. #include <clocale>
  10. #include <fcntl.h>
  11. #include <sys/stat.h>
  12. #include <sys/types.h>
  13. #include <dirent.h>
  14. #include <windows.h>
  15. #include <io.h>
  16.  
  17. #define NAME_MAX 1024
  18.  
  19. void func(
  20.     wchar_t path[],
  21.     const wchar_t dir_a[],
  22.     const wchar_t dir_b[]
  23.     );
  24.  
  25. bool FileExists(const wchar_t *wpath);
  26. bool FolderExists(const wchar_t *wpath);
  27.  
  28. void console_print(const wchar_t str[]);
  29. void CheckConsoleRedirect(void);
  30.  
  31. void PATH_A_TO_B (
  32.     const wchar_t source[],
  33.     const wchar_t a[],
  34.     const wchar_t b[],
  35.           wchar_t newstr[]
  36.     );
  37.  
  38. DWORD written = 0;
  39. static bool g_bRedirect = false;
  40.  
  41. int wmain(int argc, wchar_t *argv[] )
  42. {
  43.     setlocale( LC_ALL, ".936" );
  44.     CheckConsoleRedirect();
  45.  
  46.     if (argc > 2)
  47.     {
  48.         if (  _wopendir(argv[1]) && _wopendir(argv[2])  )
  49.         {
  50.             func( argv[1], argv[1], argv[2]);
  51.             //wprintf(L"B\n");
  52.             //func( argv[2], argv[2], argv[1]);
  53.  
  54.             fprintf(stderr, "All is done!");
  55.         }
  56.         else
  57.         {
  58.             fprintf(stderr, "Argument is not correct!");
  59.         }
  60.     }
  61.     else
  62.     {
  63.         fprintf(stderr, "Arguments not enough!");
  64.     }
  65.    
  66.     return 0;
  67. }
  68.  
  69. void func(
  70.     wchar_t path[],
  71.     const wchar_t dir_a[],
  72.     const wchar_t dir_b[]
  73.     )
  74. {
  75.     _WDIR * a = _wopendir(path);
  76.     _wdirent * dp;
  77.     _WDIR * aa;
  78.     struct stat stA;
  79.     struct stat stB;
  80.  
  81.     wchar_t fullpath[NAME_MAX] = L"";
  82.  
  83.     while (dp = _wreaddir(a))
  84.     {
  85.         if (
  86.                wcscmp(dp->d_name, L".") == 0
  87.             || wcscmp(dp->d_name, L"..") == 0  
  88.         )
  89.         {
  90.             continue;
  91.         }
  92.  
  93.         swprintf(fullpath, L"%ls\\%ls", path, dp->d_name);
  94.         wstat(fullpath, &stA);
  95.  
  96.         if ( (stA.st_mode & S_IFMT) == S_IFDIR )
  97.         {
  98.             func( fullpath, dir_a, dir_b );
  99.         }
  100.         else
  101.         {
  102.             wchar_t full_info[NAME_MAX + 32] = L"";
  103.             wchar_t mt_str[20] = L"";
  104.             wchar_t trypath[1024] = L"";
  105.  
  106.             //swprintf(full_info, L"%ld\t%ls\r\n", stA.st_mtime, fullpath );
  107.             PATH_A_TO_B( fullpath, dir_a, dir_b, trypath );
  108.             if ( ! FileExists(trypath) )
  109.             {
  110.                 swprintf(full_info, L"%8ls : %ls\r\n", L"Extra", fullpath );
  111.                 console_print( full_info );
  112.             }
  113.             else
  114.             {
  115.                 wstat(trypath, &stB);
  116.                 if (stA.st_mtime > stB.st_mtime )
  117.                 {
  118.                     swprintf(full_info, L"%8ls : %ls\r\n", L"Newest", fullpath );
  119.                     console_print( full_info );
  120.                 }
  121.                 else if ( stA.st_mtime < stB.st_mtime )
  122.                 {
  123.                     swprintf(full_info, L"%8ls : %ls\r\n", L"Newest", fullpath );
  124.                     console_print( full_info );
  125.                 }
  126.                 else
  127.                 {
  128.                     //Same
  129.                 }
  130.             }
  131.         }
  132.     }
  133.     _wclosedir(a);
  134.    
  135. }
  136.  
  137. void console_print(const wchar_t str[])
  138. {
  139.     if ( ! g_bRedirect )
  140.     {
  141.         WriteConsoleW(
  142.             GetStdHandle(STD_OUTPUT_HANDLE), str, wcslen(str)  , &written, NULL
  143.         );
  144.     }
  145.     else
  146.     {
  147.         WriteFile(
  148.             GetStdHandle(STD_OUTPUT_HANDLE), str, wcslen(str) * sizeof( str[0] ) , &written, NULL
  149.         );
  150.     }
  151. }
  152.  
  153. void CheckConsoleRedirect(void)
  154. {
  155.     if (!GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &written))
  156.     {
  157.         g_bRedirect = true;
  158.         WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\xFF\xFE", 2, &written, 0);
  159.     }
  160. }
  161.  
  162. void PATH_A_TO_B (
  163.     const wchar_t source[],
  164.     const wchar_t a[],
  165.     const wchar_t b[],
  166.           wchar_t newstr[]
  167.     )
  168. {
  169.     int len_of_a = wcslen( a );
  170.     wcscat( newstr, b );
  171.     wcscat( newstr, source + len_of_a  );
  172. }
  173.  
  174. bool FileExists(const wchar_t *wpath)
  175. {
  176.     if (_waccess(wpath, 0) == -1)
  177.     {
  178.         return FALSE;
  179.     }
  180.     else
  181.     {
  182.         return TRUE;
  183.     }
  184. }
  185.  
  186. bool FolderExists(const wchar_t *wpath)
  187. {
  188.     return !!(_wopendir(wpath));
  189. }


终端示例(部分内容用省略号表示):
Console\> Compare.exe D:\Duplicate\me H:\me
Extra : D:\Duplicate\me\....
Extra : D:\Duplicate\me\....
Newest : D:\Duplicate\me\notes\notebook.txt
Older : D:\Duplicate\me\免费获取有声读物.txt

回到 “C/C++”

在线用户

用户浏览此论坛: 没有注册用户 和 1 访客