[C/C++][文件操作] 对比目录并列出同名较新文件、较旧文件 0.1
2015-11-24 00:01
417 查看
主要是模仿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的版本。
终端示例(部分内容用省略号表示):
(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的版本。
/* g++ CompareW.cpp -municode -o CompareW */ #include <cstdio> #include <cstdlib> #include <cwchar> #include <cstring> #include <clocale> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <dirent.h> #include <windows.h> #include <io.h> #define NAME_MAX 1024 void func( wchar_t path[], const wchar_t dir_a[], const wchar_t dir_b[] ); bool FileExists(const wchar_t *wpath); bool FolderExists(const wchar_t *wpath); void console_print(const wchar_t str[]); void CheckConsoleRedirect(void); void PATH_A_TO_B ( const wchar_t source[], const wchar_t a[], const wchar_t b[], wchar_t newstr[] ); DWORD written = 0; static bool g_bRedirect = false; int wmain(int argc, wchar_t *argv[] ) { setlocale( LC_ALL, ".936" ); CheckConsoleRedirect(); if (argc > 2) { if ( _wopendir(argv[1]) && _wopendir(argv[2]) ) { func( argv[1], argv[1], argv[2]); //wprintf(L"B\n"); //func( argv[2], argv[2], argv[1]); fprintf(stderr, "All is done!"); } else { fprintf(stderr, "Argument is not correct!"); } } else { fprintf(stderr, "Arguments not enough!"); } return 0; } void func( wchar_t path[], const wchar_t dir_a[], const wchar_t dir_b[] ) { _WDIR * a = _wopendir(path); _wdirent * dp; _WDIR * aa; struct stat stA; struct stat stB; wchar_t fullpath[NAME_MAX] = L""; while (dp = _wreaddir(a)) { if ( wcscmp(dp->d_name, L".") == 0 || wcscmp(dp->d_name, L"..") == 0 ) { continue; } swprintf(fullpath, L"%ls\\%ls", path, dp->d_name); wstat(fullpath, &stA); if ( (stA.st_mode & S_IFMT) == S_IFDIR ) { func( fullpath, dir_a, dir_b ); } else { wchar_t full_info[NAME_MAX + 32] = L""; wchar_t mt_str[20] = L""; wchar_t trypath[1024] = L""; //swprintf(full_info, L"%ld\t%ls\r\n", stA.st_mtime, fullpath ); PATH_A_TO_B( fullpath, dir_a, dir_b, trypath ); if ( ! FileExists(trypath) ) { swprintf(full_info, L"%8ls : %ls\r\n", L"Extra", fullpath ); console_print( full_info ); } else { wstat(trypath, &stB); if (stA.st_mtime > stB.st_mtime ) { swprintf(full_info, L"%8ls : %ls\r\n", L"Newest", fullpath ); console_print( full_info ); } else if ( stA.st_mtime < stB.st_mtime ) { swprintf(full_info, L"%8ls : %ls\r\n", L"Newest", fullpath ); console_print( full_info ); } else { //Same } } } } _wclosedir(a); } void console_print(const wchar_t str[]) { if ( ! g_bRedirect ) { WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), str, wcslen(str) , &written, NULL ); } else { WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), str, wcslen(str) * sizeof( str[0] ) , &written, NULL ); } } void CheckConsoleRedirect(void) { if (!GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &written)) { g_bRedirect = true; WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\xFF\xFE", 2, &written, 0); } } void PATH_A_TO_B ( const wchar_t source[], const wchar_t a[], const wchar_t b[], wchar_t newstr[] ) { int len_of_a = wcslen( a ); wcscat( newstr, b ); wcscat( newstr, source + len_of_a ); } bool FileExists(const wchar_t *wpath) { if (_waccess(wpath, 0) == -1) { return FALSE; } else { return TRUE; } } bool FolderExists(const wchar_t *wpath) { return !!(_wopendir(wpath)); }
终端示例(部分内容用省略号表示):
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++版)
- strlen函数实现——string.h库函数
- c语言:分别使用for循环和while循环求5!
- 面试之C++题目汇总7
- c语言:输出(Welcome??)和(Welcome\?\?)
- 面试之C++题目汇总6
- 使用Java中的JNI技术将C/C++程序嵌入到Java代码中实现Hello World
- 面试之C++题目汇总5
- 面试之C++面试题汇总4
- 面试之C++面试题汇总3
- c语言:有趣的转义字符用法
- c语言:对于一个变量n,const用法和指针的比较
- How to call C/C++ sytle function from C# solution?
- 面试之C++题目汇总2
- 面试之C++题目汇总
- traincascade.cpp
- c语言:在屏幕上输出单引号和双引号
- c语言:枚举常量的用法举例
- TLD学习(2)-调试lk.cpp
- C#中调用c++的dll