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

Cplusplus
回复
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

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

帖子 523066680 »

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

在线用户

正浏览此版面之用户: 没有注册用户 和 0 访客