Linux C 实现文件复制、文件及文件夹删除功能

Linux下的文件操作其实是个很普通的小功能,Linux C提供了一些系统函数可以调用,我们使用的时候只需按照自己的需要封装一下即可。

1. 文件复制

实现文件从一个目录复制到另外一个目录,以下是最简单的操作,正式的工程中为了严谨起见,尽量加上错误检查。

#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
#include <unistd.h>

#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
char buff[1024];
int len;
const int BUF_LEN = 1024;

int file_copy(const char *src_file, const char *dest_file)
{
	int fd_src, fd_dest;
 
	/* 打开源文件与目标文件 */
	fd_src = open(src_file, O_RDWR | O_CREAT);
	fd_dest = open(dest_file, O_RDWR | O_CREAT);
	
	/* 循环读取源文件并写入目标文件 */
	while(len = read(fd_src, buff, BUF_LEN))
	{
		write(fd_dest, buff, len);
	}
	
	/* 关闭文件句柄 */
	close(fd_src);
	close(fd_dest);
	
	return 0;
}

int main(int argc, char const *argv[])
{
	const char *src_file_path = argv[1];
	const char *dest_file_path = argv[2];

	int ret = file_copy(src_file_path, dest_file_path);
	
	return 0;

}

2. 删除文件夹及其下面的所有文件

直接看一个程序吧,在一个给定的主路径下,通过当前时间创建子路径,再在子路径下写入几个文件,一段时间后(程序中是10秒),再将子路径及其下面的文件全部删除。

/* 用时间命名输出文件,精确到毫秒 */
string get_output_image_filename(string output_dir)
{
	char part_name[100];
	char full_name[400];

	struct timeval curr_time;
	gettimeofday(&curr_time, NULL);

	int millisec = curr_time.tv_usec % 1000;   // Get the millisencond value

	struct tm *curtime;
	time_t lt;
	time(&lt);
	curtime = localtime(&lt);

	strftime(part_name, 100, "Img_%Y-%m-%d_%H-%M-%S", curtime);
	sprintf(full_name,"%s%s-%d.bmp",output_dir.c_str(), part_name, millisec);

	printf("full_img_name = %s \n", full_name);

	return (string)full_name;
	
}

/* 给定主存储路径,获取以时间命名的下级路径 */
string get_output_image_subdir(string main_dir)
{
	char sub_dir[100];
	char full_sub_dir[256];

	struct tm *curtime;
	time_t lt;
	time(&lt);
	curtime = localtime(&lt);

	strftime(sub_dir, 100, "Images_%Y-%m-%d_%H-%M-%S", curtime);
	
	sprintf(full_sub_dir,"%s%s/",main_dir.c_str(), sub_dir);

	printf("Images output subdir is: %s \n", full_sub_dir);

	if((access(full_sub_dir, F_OK) != 0) && (mkdir(full_sub_dir, S_IRWXU) < 0))
	{
		printf("Make output image dir failed!");

		return NULL;
	}

	return full_sub_dir;
	
}

/* 给定路径和文件名,获取文件的全路径名称 */
string get_file_path(const char* input_path, char* single_file_name)
{
	char full_file_path[300];
	strcpy(full_file_path, input_path);
	
	/* Make a full directory, like this: /home/ouputfile/ */
	if(full_file_path[strlen(input_path) - 1] != '/')
	{
		strcat(full_file_path , "/");
	}
	
	/* Make a full file path, like this: /home/outputfile/file1.txt */
	strcat(full_file_path, single_file_name);
	
	printf("The full file path is: %s \n", full_file_path);
	
	return (string)full_file_path;
	
}

/* 通过递归的方式删除某个路径下的所有文件,并删除该路径 */
bool delete_file(string file_path)
{
	DIR *dir;
	struct dirent *dirinfo;
	struct stat buf;
	string fullFilePath;
	lstat(file_path.c_str(), &buf);
	
	/* Check if the path is a regular file, if it is, remove it directly.
    If it is a directory, then remove the files first, and remove the directory at last. */	
	if(S_ISREG(buf.st_mode))   // Check if it is a regular file
	{
		remove(file_path.c_str());   
	}
	else if(S_ISDIR(buf.st_mode))  // Check if it is a directory
	{
		dir = opendir(file_path.c_str());
		if(NULL == dir)
		{
			printf("Open dir failed! \n");
			return false;
		}
		
		/* Remove sub directories recursively */
		while((dirinfo = readdir(dir)) != NULL)
		{
			fullFilePath = get_file_path(file_path.c_str(), dirinfo->d_name);
			if((strcmp(dirinfo->d_name, ".") == 0) || (strcmp(dirinfo->d_name, "..") == 0))
			{
				continue;    // Ignore dot and double dots in the directory
			}
			
			/* 对函数自身进行递归调用 */
			delete_file(fullFilePath.c_str());
			rmdir(fullFilePath.c_str());
			
			printf("Delete file path: %s \n", fullFilePath.c_str());
		}
		
		closedir(dir);
		
		/* 最后删除主路径 */
		rmdir(file_path.c_str());
	}
	
	return true;
	
}



/* Test for image writing */
int main()
{
	Mat Img = imread("test.bmp");
	
	/* Image write path */
	string image_path = "./Images/";   //主路径
	if((access(image_path.c_str(), F_OK) != 0) && (mkdir(image_path.c_str(), S_IRWXU) < 0))
	{
		printf("Image output path can not accessed! \n");
		exit(1);
	}
	
	/* 获取子路径 */
	string sub_dir = get_output_image_subdir(image_path);
	string full_img_name;
	int i = 0;
	
	/* 将一个文件在创建的子路径下写入5次,形成5个文件,以备后续测试删除功能 */
	while(i < 5)
	{
		full_img_name = get_output_image_filename(sub_dir);
		
		if(full_img_name.length() == 0)
		{
			printf("File name error! \n");
			exit(1);
		}
	
		imwrite(full_img_name, Img);
		
		sleep(1);
		
		i++;
	}
	
	sleep(10);
	
	/* 文件写入10秒后删除文件及其所在的子路径 */
	bool is_del = delete_file(sub_dir);
	if(is_del)
	{
		printf("Successfully deleted the path and files. \n");
		
	}
	else
	{
		printf("Delete path and files failed. \n");
	}
	
	return 0;
}

上例中定义了一个函数:delete_file(string file_path),该函数通过对自己的递归调用实现路径file_path及其下所有文件的删除。在该函数中,用到的函数和结构体需要简单说明下:

2.1 DIR

找到的定义如下:

struct __dirstream
{
	void *__fd;          //  pointer for descriptor
	char *__data;        // Directory block
	int __entry_data;    // Entry number `__data' corresponds to
	char *__ptr;         // Current pointer into the block
	int __entry_ptr;     //  Entry number `__ptr' corresponds to
	size_t __allocation;   // Space allocated for the block
	size_t __size;         // Total valid data in the block
	__libc_lock_define (, __lock)   // Mutex lock for this structure
};

typedef struct __dirstream DIR;

2.2 struct dirent

该结构体是用来获取某文件夹目录内容。定义如下,释义来自百度百科。上例中是用来获取某目录下的文件名称,即dirinfo->d_name。

struct dirent
{
	long d_ino;                /* inode number 索引节点号 */
	off_t d_off;               /* offset to this dirent 在目录文件中的偏移 */
	unsigned short d_reclen;   /* length of this d_name 文件名长 */
	unsigned char d_type;      /* the type of d_name 文件类型 */
	char d_name [NAME_MAX+1];   /* file name (null-terminated) 文件名,最长256字符 */
}

2.3 struct stat

上例中,该结构体用来存放某目录的详细信息,通过执行lstat(file_path.c_str(), &buf),将file_path表示的路径的详细信息存储在stat类型的buf结构体中。后面通过执行S_ISREG(buf.st_mode)、S_ISDIR(buf.st_mode)判断当前路径是常规文件,还是一个路径。

struct stat 
{
	mode_t     st_mode;       //文件访问权限
	ino_t      st_ino;       //索引节点号
	dev_t      st_dev;        //文件使用的设备号
	dev_t      st_rdev;       //设备文件的设备号
	nlink_t    st_nlink;      //文件的硬连接数
	uid_t      st_uid;        //所有者用户识别号
	gid_t      st_gid;        //组识别号
	off_t      st_size;       //以字节为单位的文件容量
	time_t     st_atime;      //最后一次访问该文件的时间
	time_t     st_mtime;      //最后一次修改该文件的时间
	time_t     st_ctime;      //最后一次改变该文件状态的时间
	blksize_t  st_blksize;    //包含该文件的磁盘块的大小
	blkcnt_t   st_blocks;     //该文件所占的磁盘块
};

2.4 删除文件remove()

函数原型如下,输入参数可以是一个路径,也可以是一个常规文件名。但如果是路径,只能是空路径,如果路径非空,调用remove是无法将其删除的,因此才有上面例子中的递归调用。

#include <stdio.h>
int remove(char * filename);

2.5 路径操作:

用到的几个dir操作如下,比较简单,不过多解释。

#include<sys/types.h>
#include<dirent.h>

DIR* opendir (const char * path );
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dir);
int rmdir(const char *dirname );
发布了57 篇原创文章 · 获赞 58 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/DeliaPu/article/details/103227604