Windows实现一个功能:删除指定目录下最后一次修改时间在两分钟之前的文件夹

环境:windows10,VS2013

函数功能:删除指定目录下最后一次修改时间在两分钟之前的文件夹(这个时间可以自己设置)

功能具体描述:删除指定目录下的以“sid_”开头命名的满足特定条件的文件夹,对于该目录下其他的文件和文件夹不做任何操作。

对于以“sid_”开头命名的文件夹来说,满足什么样的条件才把它删除呢?就是当该文件夹下的所有文件(File)的最后一次修改时间都在两分钟之前,就把这个文件夹删除,如果有一个文件是在两分钟之内修改的,则不删除;如果该文件夹为空,不管是不是两分钟之内建立的,直接删除!

注意,我这里默认,“sid_”开头的文件夹下只有文件(File),不含有文件夹(Directory)!

 

代码如下。下面我首先来说说如何执行这个代码。

1. 在VS上新建一个空项目,将下面的代码复制上去,项目的名字我这里起的是叫做deleteFile;

2. 在代码的116行,将 char   path[MAX_PATH] = "D:\\test\\deleteFile\\deleteFile"; 后面替换成一个任意的路径,待会就在这个路径下创建文件件,方便测试,注意这里都是双斜杠!

3. 有了上面两步,程序已经可以直接运行了,但是为了测试效果,还需要在刚才的路径下新建几个“sid_”开头命名的文件夹和文件,如下图:

我这里新建了三个文件夹sid_01、sid_03、sid_03和一个文件sid_04.txt,并且在sid_01和sid_02下都新建了一个文本文件,sid_03为空,这样是为了观察不同情况下的实验结果。

4. 等待两分钟(因为我这里设置的时间是两分钟),打开sid_01目录下的a.txt,在其中随便输入几个字符,保存。

    运行程序,结果如下图:

    

  sid_01由于其中的文件在两分钟之内做了修改,没有被删除,而sid_04.txt不是文件夹,也没有被删除,符合预期。

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys\stat.h>
#include <Windows.h>
#define snprintf(dest, size, format, ...) _snprintf_s(dest, size, (size) - 1, format, ## __VA_ARGS__)
#define SEP_CHAR "\\"

typedef WIN32_FIND_DATAA WIN32_FIND_DATA;

typedef struct _delName  // 待删除的文件或者文件夹的名字
{
	char name[100];
}delName;

// FileTimeToTime_t()
// 功能:将FILETIME类型的变量ft转化成time_t类型,并保存在指针t中
// 这段代码从网上copy的,随便一搜就搜到了
void  FileTimeToTime_t(FILETIME  ft, time_t  *t)
{
	LONGLONG  ll;

	ULARGE_INTEGER            ui;
	ui.LowPart = ft.dwLowDateTime;
	ui.HighPart = ft.dwHighDateTime;

	*t = ((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000);
}

// is_2mins_ago()
// 功能:判断入参的文件(File)是否是在2min中之内是否进行过写的操作,如果是就return TRUE,否则return FALSE
BOOL is_2mins_ago(WIN32_FIND_DATA *file)
{
	time_t curTime;
	time_t lastWriteTime;
	time_t numSec = 2 * 60;  // 2分钟包含 2*60 秒
	time(&curTime);
	FileTimeToTime_t((*file).ftLastWriteTime, &lastWriteTime);
	if ((curTime - lastWriteTime) > numSec)
		return TRUE;
	return FALSE;
}

// isDelete()
// 功能:判断入参的文件夹(Directory)是否需要删除,如果是就return TRUE,否则return FALSE
// 参数:path指的是该文件夹所在的路径,dir就是该文件夹
BOOL isDelete(char* path, WIN32_FIND_DATA *dir)
{
	WIN32_FIND_DATA p;
	char   buf[MAX_PATH] = { 0 };
	snprintf(buf, sizeof(buf), "%s%s%s%s*.txt", path, SEP_CHAR, (*dir).cFileName, SEP_CHAR);
	HANDLE	h = FindFirstFile(buf, &p);
	if (NULL == h)  // 该文件夹为空是否删除?
	{
		return TRUE;
	}
	if (!is_2mins_ago(&p))
	{
        FindClose(h);
		return FALSE;
	}
	while (FindNextFile(h, &p))
	{
		if (!is_2mins_ago(&p))
		{
            FindClose(h);
			return FALSE;
		}
	}
	FindClose(h);
	return TRUE;  // 该文件夹需要删除就return 1,否则return 0
}

// DeleteDirectory()
// 功能:删除path路径指定的文件夹,删除文件夹成功return TRUE,失败return FALSE
// 注:我这里默认该文件夹下只有文件,没有文件夹了,如果想删除带有文件夹的文件夹,请参考:https://blog.csdn.net/jaff20071234/article/details/6559533
BOOL DeleteDirectory(const char * path)
{
	char   buf[MAX_PATH] = { 0 };
	snprintf(buf, MAX_PATH, "%s%s*.*", path, SEP_CHAR); //匹配格式为*.*,即该目录下的所有文件  
	WIN32_FIND_DATAA p;
	ZeroMemory(&p, sizeof(WIN32_FIND_DATAA));
	HANDLE h = FindFirstFile(buf, &p);
	if (strcmp(p.cFileName, ".") && strcmp(p.cFileName, ".."))
	{
		snprintf(buf, sizeof(buf), "%s%s%s", path, SEP_CHAR, p.cFileName);
		DeleteFile(buf);
	}
	while (FindNextFile(h, &p))
	{
		if (strcmp(p.cFileName, ".") && strcmp(p.cFileName, "..")) //如果不是"." ".."目录  
		{
			snprintf(buf, sizeof(buf), "%s%s%s", path, SEP_CHAR, p.cFileName);
			DeleteFile(buf);
		}
	}
	FindClose(h);  // 这一句不能放在该函数的最后,否则可能会导致后面的删除文件夹失败(你可以试试看)

	BOOL bRet = RemoveDirectory(path);
	if (bRet == 0) //删除目录  
	{
		printf("delet directory faild!path: %s\n", path);
		return FALSE;
	}
	return TRUE;
}

// delete_logDir_2mins_ago()
// 功能:对path这个变量指定目录下所有sid_开头的文件夹,如果该文件夹下没有文件,则删除;如果该文件夹下只要存在一个文件
//       是在当前时间的两分钟之内进行过写操作,则该文件夹保存,否则该将该文件夹删除
void delete_logDir_2mins_ago()
{
	WIN32_FIND_DATA p;
	int num = 0;
	delName d[100];
	char   path[MAX_PATH] = "D:\\test\\deleteFile\\deleteFile";  // 这里的路径一定要用两个斜杠!
	char   buf[MAX_PATH] = { 0 };

	snprintf(buf, sizeof(buf), "%s%ssid_*", path, SEP_CHAR);

	HANDLE	h = FindFirstFile(buf, &p);
	if (NULL == h)
	{
		return;
	}
	if (p.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  // 判断是否为文件夹,参考:https://blog.csdn.net/c20081052/article/details/79912291
	{
		if (isDelete(path, &p))
		{
			snprintf(d[num].name, sizeof(d[num].name), "%s", p.cFileName);
			num++;
		}
	}

	while (FindNextFile(h, &p) && num<100)
	{
		if (p.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  // 判断是否为文件夹
		{
			if (isDelete(path, &p))
			{
				snprintf(d[num].name, sizeof(d[num].name), "%s", p.cFileName);
				num++;
			}
		}
	}

	FindClose(h);  // 这一句不能放在该函数的最后,否则可能会导致后面的删除文件夹失败(你可以试试看)

	for (int j = 0; j < num; j++)
	{
		snprintf(buf, sizeof(buf), "%s%s%s", path, SEP_CHAR, d[j].name);
		DeleteDirectory(buf);
	}
}

int main()
{
	delete_logDir_2mins_ago();

	system("pause");
	return 0;
}

在写代码的过程中发现以下几个值得注意或者学习的地方,顺便在此贴出来:

1. 代码中关闭由于打开句柄使用的是FindFirstFile()和FindNextFile()函数,应当使用FindClose()函数来关闭句柄,否则可能会存在句柄泄露的问题(不过我到现在还不明白句柄到底是个啥玩意)。

2. 我刚写完这个程序时,为了图方便,自己另外写了一个函数generateDir()用来自动生成图中的那些文件夹,然后在main函数中同时调用generateDir()和delete_logDir_2mins_ago(),可是在运行的时候却发现,一个文件/文件夹都没有被删除!最终发现,貌似无法在一个进程中生成文件/文件夹然后又把它删除,因为这些文件/文件夹貌似与这个进程关联起来了什么的。。。(我也不是很懂),所以最后还是每次自己手动创建文件夹来测试。其实也可以在main函数中每次注释掉一个函数,再执行另一个函数,就没问题了。

3. 关于为什么要把FILETIME类型转换成time_t类型?因为time_t类型是以秒为单位的,方便计算吧~目前据我了解Windows中有三个常用的时间类型time_t,FILETIME,SYSTEMTIME,有时间可以去学学,这三个类型的互相转换网上也有很多资料。

4. 在阅读Windows的程序时,经常会发现下面类似的宏定义:

   

#define FindFirstFile  FindFirstFileA

一直不懂为什么要在函数名后面加个大写的A,经过搜索资料后,下图应该可以帮助理解:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值