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

作者 523066680@163.com,转载请注明出处:[C/C++][文件操作]目录/文件夹对比并列出同名较新文件、较旧文件 V1

 

主要是模仿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的版本。

 

  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
posted @ 2015-11-24 00:01  vicyang  阅读(569)  评论(1编辑  收藏  举报