欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux-C 遍历目录,复制目录

程序员文章站 2022-06-13 22:38:05
...

Linux-C 遍历目录,复制目录

一、简述

         记--递归方法遍历目录,复制目录,也可以利用强大的shell命令获取目录下指定格式的文件。

二、例子

       1、递归方法

        测试代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <libgen.h>

/*
 *display_dir:递归遍历目录,打印所有文件路径名
 *@dir_path:目录路径
 *
 */
void display_dir( char *dir_path )
{
	//排除是"."目录、".."目录   (在Linux,每个目录都有"."目录、".."目录,"."表示当前目录,".."是上级目录)
	if( strcmp( dir_path, "." ) == 0 || strcmp( dir_path, ".." )  == 0 )
	{
		return;
	}

	DIR *dir_ptr;//目录指针
	struct dirent *file_info;//目录项指针,存放目录项的相关信息比如文件类型

	dir_ptr = opendir( dir_path );//打开目录
	if( dir_ptr == NULL )
	{
			return ;
	}

	//为了统一输出方式,比如要打开的目录a里面有个1.txt,
	//传目录a和传a/进来都显示a/1.txt,而不会一个是a//1.txt
	int dir_len = strlen( dir_path );//Linux兼容 a/1.txt 和 a//1.txt
	if( dir_path[dir_len-1] == '/')
	{
		dir_path[dir_len-1] = '\0';
	}

	char sub_dir[512] = {0};//临时存放子目录名称

	while( file_info = readdir( dir_ptr ) )//每次循环读取一个目录项(一个文件)
	{
		switch( file_info->d_type )//根据文件类型执行相应动作,
		{
			case DT_DIR: //如果是目录就递归遍历
				    if( strcmp( file_info->d_name, ".") != 0 && strcmp(file_info->d_name, "..")  != 0 )
    			            {
				     	sprintf( sub_dir, "%s/%s", dir_path, file_info->d_name );
				     	display_dir( sub_dir );
				    }
				   break; 
			case DT_BLK: 
			case DT_CHR:
			case DT_FIFO:
			case DT_LNK:
			case DT_REG: //常规文件 .txt .bmp .jpg .c 可执行文件 等等
			case DT_SOCK:
			case DT_UNKNOWN:printf( "%s/%s\n", dir_path, file_info->d_name );//其他文件直接显示
				     break;
			default:
				break;
		}

	}
	
	closedir( dir_ptr );//关闭目录
}

int main(int argc, char *argv[])
{
	//main函数参数在执行时传进来,比如./hello jack  argc=2,argc[0]=./hello,argv[1]=jack
	if(argc != 2)
	{
		printf("argc error!\n");
		return -1;
	}

	display_dir( argv[1] );//调用目录打印函数

	return 0;
}

        运行效果

        Linux-C 遍历目录,复制目录

       2、利用shell命令(待补充)

三、复制目录

       程序将要复制的目录路径dir1 复制到 目标路径dir2下。

       测试代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <libgen.h>

void copy_file(char *dest_dir, char *src_dir, char * filename )
{
	char tmp_src_dir[512] = {0};
        char tmp_dest_dir[512] = {0};
 
        sprintf( tmp_dest_dir, "%s/%s", dest_dir, filename );
        sprintf( tmp_src_dir, "%s/%s", src_dir, filename );


	FILE *src_fp = fopen( tmp_src_dir ,"r" );
	if(!src_fp)
	{
		perror("open file error!");
		return ;
	}

	FILE *dest_fp = fopen( tmp_dest_dir, "w");
	if(!dest_fp)
	{
		perror("open file error!");
		return ;
	}

	char buffer[1024*128];
	char *tmp;
	int rd_ret;
	int wr_ret;

	while(1)
	{
		rd_ret = fread(buffer, 1, sizeof(buffer), src_fp);
		if(rd_ret == 0 )
		{
			break;
		}

                tmp = buffer;
		while(1)
		{
			wr_ret = fwrite(tmp, 1, rd_ret, dest_fp);
			if(wr_ret == rd_ret)
			{
				break;
			}
			else
			{
				rd_ret -= wr_ret;
				tmp += wr_ret;
			}
		}
	}

}

void _copy_dir( char *src_dir_path, char *dest_dir_path )
{

	if( strcmp( src_dir_path, "." ) == 0 || strcmp( src_dir_path, ".." )  == 0 )
	{
		return;
	}

	DIR *src_dp, *dest_dp;
        struct dirent *file_info;

        src_dp = opendir( src_dir_path );
        if( src_dp == NULL )
        {
                return ;
        }

	
	int dir_len = strlen( src_dir_path );
	if( src_dir_path[dir_len-1] == '/')
	{
		src_dir_path[dir_len-1] = '\0';
	}
	dir_len = strlen( dest_dir_path );
	if( dest_dir_path[dir_len-1] == '/')
	{
		src_dir_path[dir_len-1] = '\0';
	}
	
	char tmp_src_dir[512] = {0};
	char tmp_dest_dir[512] = {0};

	sprintf( tmp_dest_dir, "%s/%s", dest_dir_path, basename( src_dir_path ) );
	dest_dp = opendir( tmp_dest_dir );

        if( dest_dp == NULL )
        {
                mkdir( tmp_dest_dir, 0777);
        }
        else
        {
                closedir( dest_dp );
        }
	

	while( file_info = readdir( src_dp ) )
	{
		switch( file_info->d_type )
		{
			case DT_DIR: 
				    if( strcmp( file_info->d_name, ".") != 0 && strcmp(file_info->d_name, "..")  != 0 )
    			            {
				     	sprintf( tmp_src_dir, "%s/%s", src_dir_path, file_info->d_name );
				     	_copy_dir( tmp_src_dir, tmp_dest_dir );
				    }
				   break; 
			case DT_BLK: 
			case DT_CHR:
			case DT_FIFO:
			case DT_LNK:
			case DT_REG:
			case DT_SOCK:;
			case DT_UNKNOWN:copy_file( tmp_dest_dir, src_dir_path, file_info->d_name);
				     break;
			default:
				break;
		}

	}
	
	closedir( src_dp );
}

void copy_dir( char *src_dir_path, char *dest_dir_path )
{
	DIR *dest_dp;
	dest_dp = opendir( dest_dir_path );
	if( dest_dp == NULL )
	{
		if( mkdir( dest_dir_path, 0777 ) == -1 )
		{
			perror( "mkdir error!\n" );
			return ;
		}
	}
	else
	{
		closedir( dest_dp );
	}
	_copy_dir( src_dir_path, dest_dir_path );
}
int main(int argc, char *argv[])
{
	if(argc != 3)
	{
		printf("argc error!\n");
		return -1;
	}

	copy_dir(argv[1], argv[2]);

	return 0;
}

       运行结果:

       Linux-C 遍历目录,复制目录

      Linux-C 遍历目录,复制目录

四、总结

      1、opendir()函数

           在第三本man手册,在终端输入命令:man 3 opendir 进行查询

          函数原型及头文件

          Linux-C 遍历目录,复制目录

         函数返回值,成功返回目录指针,失败返回NULL并设置全局错误号

         Linux-C 遍历目录,复制目录

 2、readdir()函数

        在第三本man手册,在终端输入命令:man 3 readdir 进行查询

       函数原型及头文件

       Linux-C 遍历目录,复制目录

       返回值

       Linux-C 遍历目录,复制目录

       成功时,readdir()返回指向dirent结构的指针。 (这种结构可能是静态分配的;不要试图释放它。)
        如果到达目录流的末尾,则返回NULL并且不更改errno。 如果发生错误,则返回NULL并正确设置errno。 要区分流的结尾和错误,请在调用readdir()之前将errno设置为零,然后检查errno的值是否返回NULL。

      目录项结构体struct drient

      Linux-C 遍历目录,复制目录

      其中的d_type就是文件类型

     Linux-C 遍历目录,复制目录