作者 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的版本。

 /*
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 = ;
static bool g_bRedirect = false; int wmain(int argc, wchar_t *argv[] )
{
setlocale( LC_ALL, ".936" );
CheckConsoleRedirect(); if (argc > )
{
if ( _wopendir(argv[]) && _wopendir(argv[]) )
{
func( argv[], argv[], argv[]);
//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 ;
} 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".") ==
|| wcscmp(dp->d_name, L"..") ==
)
{
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 + ] = L"";
wchar_t mt_str[] = L"";
wchar_t trypath[] = 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[] ) , &written, NULL
);
}
} void CheckConsoleRedirect(void)
{
if (!GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &written))
{
g_bRedirect = true;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\xFF\xFE", , &written, );
}
} 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, ) == -)
{
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/C++][文件操作] 对比目录并列出同名较新文件、较旧文件 0.1的更多相关文章

  1. Linux基础(10)AIO项目设计与POSIX文件操作和目录管理

    实现fast-cp :拷贝文件到目标对象 Linux的七种文件类型 :https://blog.csdn.net/linkvivi/article/details/79834143 ls -al :h ...

  2. C# 文件操作(全部) 追加、拷贝、删除、移动文件、创建目录 修改文件名、文件夹名

    原文:C# 文件操作(全部) 追加.拷贝.删除.移动文件.创建目录 修改文件名.文件夹名 本文也收集了目前最为常用的C#经典操作文件的方法,具体内容如下:C#追加.拷贝.删除.移动文件.创建目录.递归 ...

  3. Python 文件复制&按目录树结构拷贝&批量删除目录及其子目录下的文件

    文件复制&按目录树结构拷贝&批量删除目录及其子目录下的文件 by:授客 QQ:1033553122 测试环境: Python版本:Python 3.3.2 Win7 64 代码实践 # ...

  4. 通过某个进程号显示该进行打开的文件 lsof -p 1 11. 列出多个进程号对应的文件信息 lsof -p 123,456,789 5. 列出某个用户打开的文件信息 lsof -u username

    linux命令 — lsof 查看进程打开那些文件 或者 查看文件给那个进程使用 lsof命令是什么? 可以列出被进程所打开的文件的信息.被打开的文件可以是 1.普通的文件,2.目录  3.网络文件系 ...

  5. Python [习题] 文件操作:目录间copy 文件

    [习题] 指定一个源文件,实现copy到目标目录.例如把/tmp/sample1.txt 拷贝到/tmp/sample2.txt原文件需要有读权限(默认rt权限),目标文件需要给写(w即可)权限. I ...

  6. python文件操作【目录大全】

    总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...

  7. linux 文件操作与目录操作

    文件操作 使用命令 命令格式: 命令 [选项] [参数] [] 表示可选的 示例: ls -a /etc 常识命令 ls:查看指定目录的内容,不指定目录时查看当前工作目录 选项 说明 -a 显示所有文 ...

  8. 说说Python 中的文件操作 和 目录操作

    我们知道,文件名.目录名和链接名都是用一个字符串作为其标识符的,但是给我们一个标识符,我们该如何确定它所指的到底是常规文件文件名.目录名还是链接名呢?这时,我们可以使用os.path模块提供的isfi ...

  9. node.js整理 03文件操作-遍历目录和文本编码

    遍历目录 递归算法 遍历目录时一般使用递归算法,否则就难以编写出简洁的代码. 递归算法与数学归纳法类似,通过不断缩小问题的规模来解决问题 function factorial(n) { if (n = ...

随机推荐

  1. Node.js 在 PayPal实战

    之前有过一个谈了很多关于PayPal移动到node.js的一个应用平台.作为设置我的免费用户界面的第1部分的延续,我很高兴地说,这些传言是真的,我们的Web应用程序正在从Java迁移到JavaScri ...

  2. struts1+spring+myeclipse +cxf 开发webservice以及普通java应用调用webservice的实例

    Cxf + Spring+ myeclipse+ cxf 进行  Webservice服务端开发 使用Cxf开发webservice的服务端项目结构 Spring配置文件applicationCont ...

  3. 消息中间件的技术选型心得-RabbitMQ、ActiveMQ和ZeroMQ

    消息中间件的技术选型心得-RabbitMQ.ActiveMQ和ZeroMQ 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs RabbitMQ.Active ...

  4. WWDC2016-session401-CodeSign大改版

    自动签名机制和手动签名都明显看起来很好用. 自动签名有log 手动签名有具体的错误提示信息. session401 Xcode Signing. 亲,你的眼睛好大 相声演员吗? Yeah,You ar ...

  5. Centos 6.5 下安装socket5代理

    ---恢复内容开始--- 1. 安装 先安装依赖库 yum -y install gcc gcc-c++ automake make pam-devel openldap-devel cyrus-sa ...

  6. 解决mac os x下 tomcat启动报 java.net.BindException: Permission denied <null>:80 错误

    我在mac os x上启动tomcat的时候,报 java.net.BindException: Permission denied <null>:80,java.net.BindExce ...

  7. Mac下MySQL卸载方法 转载

    mac下mysql的DMG格式安装内有安装文件,却没有卸载文件……很郁闷的事. 网上搜了一下,发现给的方法原来得手动去删. 很多文章记述要删的文件不完整,后来在stackoverflow这里发现了一个 ...

  8. bss段和data段的区别

    一般情况下,一个程序本质上都是由 bss段.data段.text段三个组成的——本概念是当前的计算机程序设计中是很重要的一个基本概念.而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大 ...

  9. Oracle 11g EM安全证书问题无法访问的解决办法

    OS: Windows Server 2012 Oracle: 11g R2 上一篇 Oracle 11g EM删除重建的方法 通过命令的方式重建了EM,启动也成功 emctl status dbco ...

  10. windows 程序设计自学:添加字符串资源

    #include <windows.h> #include "resource.h" LRESULT CALLBACK MyWndProc( HWND hwnd, // ...