C语言—遍历查找并删除文件包括子文件

准备阶段

在完成这个遍历删除任务之前,我们要先完成一下准备阶段的任务。最重要的就是**_**finddata_t结构体的使用和remove()以及rmdir()函数的使用。
首先remove()函数是用来删除文件的
头文件:#include <stdio.h>
remove()函数用于删除指定的文件,其原型如下:
int remove(char * filename);成功则返回0,失败则返回-1,
这里 * filename指针是一个指向字符串常量的地址,也就是需要删除的文件名字如
“D://text//123.txt” 这就是一个我们需要操作的地址
需要注意的是remove()函数我用来删除单个的文件,当文件夹内为空时,我才用rmdir()函数来删除空的文件夹(当然也只能删除空文件夹);

接下来我们要了解一下_finddata_t结构体用法。
Struct _finddata_t是用来存储文件各种信息的结构体,使用这个结构体要引用的头文件为“ #include <io.h>”它的结构体定义如下:


struct _finddata_t
        {
             unsigned attrib;
             time_t time_create;
             time_t time_access;
             time_t time_write;
             _fsize_t size;
             char name[_MAX_FNAME];
        };

unsigned attrib:无符号整形、位表示。它的作用是表示文件的属性,一般来说,文件的属性有如下几种:

_A_ARCH(存档)、 _A_HIDDEN(隐藏)、_A_NORMAL(正常)、_A_RDONLY(只读)、_A_SUBDIR(文件夹)、_A_SYSTEM(系统)

time_t time_create:表示从1970年1月1日0时0分0秒到现在时刻的秒数。实际上就是长整形变量 long int

time_t time_access:文件最后一次被访问的时间

time_t time_write:文件最后一次被修改的时间

_fsize_t size:文件的大小。

char name[_MAX_FNAME]:文件的文件名,这里的_MAX_FNAME是一个常量宏,它在头文件中被定义,表示的是文件名的最大长度。

与这个结构体配对的函数为_findfirst、_findnext和_fineclose。
下面解释这三个函数的作用

long _findfirst( char *filespec, struct _finddata_t *fileinfo );

返回值:如果查找成功,那么就返回一个long型的唯一查找用的句柄。这个句柄会在_findnext函数中被使用。失败的话就会返回0.

参数:filespec:标明文件的字符串。例如:*.c
fileinfo:这里就是用来存放文件信息的结构体的指针。函数成功后,函数会把找到的文件的信息放入这个结构体所分配的内存空间中。

int _findnext( long handle, struct _finddata_t *fileinfo );

返回值:若成功返回0,否则返回-1。

参数:handle:即由_findfirst函数返回回来的句柄。

int _findclose( long handle );

返回值:成功返回0,失败返回-1。
该结构体和搭配的函数使用的逻辑就是先用_findfirst查找第一个文件,若成功则用返回的句柄,调用_findnext函数查找其他的文件,当查找完毕后用,用_findclose函数结束查找。

正式开始,下面为查询程序

#include<io.h>
#include <direct.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
void findfile(char path[], char mode[])
{
	struct _finddata_t file;
	long HANDLE;
	char Onepath[100];
	int i = 0;
	strcpy(Onepath, path);
	strcat(Onepath, mode);
	HANDLE = _findfirst(Onepath, &file);
	if (HANDLE != -1)
	{
		do {
			//判断是否有子目录  
			if (file.attrib & _A_SUBDIR)//_A_SUBDIR 判断是否为文件夹
			{
				//判断是否为"."当前目录,".."上一层目录
				if ((strcmp(file.name, ".") != 0) && (strcmp(file.name, "..") != 0))
				{
					char newPath[100];
					strcpy(newPath, path);
					strcat(strcat(newPath, "\\"), file.name);
					findfile(newPath, mode);
				}
			}
			else
			{
				i++;
				printf("%s \n", file.name);
				char Del_file_name[100];
				strcpy(Del_file_name, path);
				strcat(Del_file_name, "\\");
				strcat(Del_file_name, file.name);
				remove(Del_file_name);
				rmdir(path);
			}
		} while (_findnext(HANDLE, &file) == 0);
	}
	else
	{
		printf("can't open the path\n");
	}
	_findclose(HANDLE);
	printf("Find %d files\n", i);
}

int main()
{
	char mode[100] = "\\*.*";
	char path[100] = "D:\\text";
	findfile(path, mode);
	return 0;
}

为了便于在编译调试时,方便理解file.name的值,从而理解程序的执行过程,我在这附上一张cmd指令查看的目标文件的图
在这里插入图片描述

下面为删除程序(注意路径小心操作)(未优化)

该程序的运行方式和其他删除程序方式可能有些许不同,本程序的流程是先将一个文件夹的内容对应后缀文件删除完毕后,才进入下一个子文件夹继续删除,而一些人的流程是,遇到子文件夹便进入删除完毕后在退出,最后删除母文件夹的文件。我的流程更加符合人的操作方式,先完成一层任务后在进入下一层

匆忙完成,对一些细节还没有彻底优化操作

#include<io.h>
#include <direct.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;

void findfile(char path[], char mode[], char s_name[]);
bool judge_name(char del_name[], char judgename[]);
#include"del_file.h"

char del_filename[512];
char *p = del_filename;
char *q = p;
void findfile(char path[], char mode[], char s_name[])
{
	struct _finddata_t file;
	long handle;
	char delpath[100];
	int i = 0;

	strcpy(delpath, path);
	strcat(delpath, mode);

	handle = _findfirst(delpath, &file);
	if (handle != -1)
	{
		do{
			if (file.attrib & _A_SUBDIR)//_a_subdir 判断是否为文件夹
			{
				if ((strcmp(file.name, ".")!= 0) && (strcmp(file.name, "..") != 0))
				{
					char newpath[100];
					strcpy(newpath, path);
					strcat(strcat(newpath, "\\"), file.name);
					strcat(strcat(del_filename, newpath), ";");
				}
			}
			else
			{
				//printf("%s \n", file.name);
			    char del_file_name[100];
				strcpy(del_file_name, path);
				strcat(strcat(del_file_name, "\\"), file.name);
			    cout << del_file_name << endl;
				if (judge_name(del_file_name, s_name))
				{
					remove(del_file_name);
					rmdir(path);
				}		
			}		

		} while (_findnext(handle, &file) == 0);		
	}
	else
	{
		printf("can't open the path\n");
	}
	_findclose(handle);
	printf("find %d files\n", i);
	while (*q != '\0')
	{
		char filename[50];
		char *f = filename;
		while (*q != ';'){ q++; }
		memcpy(f, p, (q - p)*sizeof(char));
		f = f + (q - p) ;
		*f = '\0';
		q += 1;
		p = q;
	    cout << filename<<endl;
		findfile(filename, mode, s_name);
	}
}

bool judge_name(char del_name[], char judgename[])
{
	int n = strlen(del_name);
	char *p = del_name;
	p = p + n - 1;
	while (*p != '.'){ p--; }
	char *f = p;  
	char *q = judgename;
	while (*p != '\0')
	{
		if (*p != *q)
		{
			p = f;
			while (*q != '.')
			{
				if (*q == '\0')
					return false;
				q++;
			}
			
		}
		else
		{
			p++;
			q++;
		}
	}
	return true;
}
int main()
{
	char mode[100] = "\\*.*";
	char path[100] = "D:\\text";
	char s_name[20] = ".txt.bmp.xlsx";

	findfile(path, mode, s_name);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值