Linux下C语言实现文件遍历,支持嵌套和文件数量统计

Linux命令行下有两个非常基本的命令,一个是ls,一个是tree,其分别能够列出当前目录下的文件和树形方式嵌套显示目录结构。


因为网络上有很多版本的文件遍历代码,代码都没有整理过,看起来也很累,这里正好有点时间汇总整理下,并做一个练习。


同时,对一些POSIX淘汰接口进行一些解释,来帮助大家了解为什么有的代码会segfault。


通用版本的dir嵌套遍历

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

#define PATH_LEN 1024

int count = 0;

void dir_scan(char *path, char *file)
{
	struct stat s;
	DIR *dir;
	struct dirent *dt;
	char dirname[PATH_LEN];

	memset(dirname, 0, PATH_LEN*sizeof(char));
	strcpy(dirname, path);

	if(stat(file, &s) < 0)
	{
		printf( "lstat error\n ");
	}

	if(S_ISDIR(s.st_mode))
	{
		strcpy(dirname+strlen(dirname), file);
		strcpy(dirname+strlen(dirname), "/");
		if((dir = opendir(file)) == NULL)
		{
			printf( "opendir %s/%s error\n ");
			exit(4);
		}
		
		if(chdir(file) < 0) 
		{
			printf( "chdir error\n ");
			exit(5);
		}
		
		while((dt = readdir(dir)) != NULL)
		{
			if(dt-> d_name[0] == '.')
			{
				continue;
			}

			dir_scan(dirname, dt-> d_name);
		}
		
		if(chdir( "..") < 0)
		{
			printf( "chdir error\n ");
			exit(6);
		}
	}else
	{
		printf( "%s%s\n ", dirname, file);
		count++;
	}
}

int main(int argc, char *argv[])
{
	struct stat s;

	if(argc != 2)
	{
		printf( "dir path needed.\n ");
		exit(1);
	}
	
	if(lstat(argv[1], &s) < 0)
	{
		printf( "lstat error\n ");
		exit(2);
	}
	
	if(!S_ISDIR(s.st_mode))
	{
		printf( "%s is not a dir name\n ", argv[1]);
		exit(3);
	}

	dir_scan( "", argv[1]);

	printf( "total:   %d   files\n ",   count);

	exit(0);
}

编译并执行命令

$ gcc dir.c -o dir
$ ./dir version/
version//version.tar.gz
 version//version.h
 version//main.c
 version//version.c
 version//Makefile
 total:   5   files

文件时间信息dir嵌套遍历

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

#define PATH_LEN 1024

int global_count = 0;

void do_search_dir(char *path)
{ 
	DIR *dir; 
	char fullpath[PATH_LEN],currfile[PATH_LEN]; 
    struct dirent *s_dir; 
    struct stat file_stat; 
	int local_count = 0;

	strcpy(fullpath,path); 
	dir=opendir(fullpath); 
	while((s_dir=readdir(dir)) != NULL)
	{ 
        if((strcmp(s_dir-> d_name, ".")==0)||(strcmp(s_dir-> d_name, "..")==0))
		{
		    continue; 
		}

        sprintf(currfile, "%s/%s",fullpath,s_dir-> d_name); 
        stat(currfile,&file_stat); 
        if(S_ISDIR(file_stat.st_mode)) 
		{
			printf("\n------[Directory] %s is Directory,Judged by S_ISDIR\n", s_dir-> d_name);
            do_search_dir(currfile); 
        } else 
		{
			printf("\n[File] %s; path: %s\n",s_dir-> d_name, currfile);
			printf("Owner ID: %d,Group ID: %d\n",file_stat.st_uid,file_stat.st_gid);

			printf("Last Access Time: %s",ctime(&file_stat.st_atime));
			printf("Last Modification Time: %s",ctime(&file_stat.st_mtime));
			printf("Last Status Change Time: %s",ctime(&file_stat.st_ctime));
			global_count++;
			local_count++;
		}
    } 
	
	printf( "^^^^^^[Directory] %s local count:   %d   files\n", path, local_count);
    closedir(dir); 
} 
int main(int argc, char **argv)
{ 
	struct stat s;

	if(argc != 2)
	{
		printf( "dir path needed.\n ");
		exit(1);
	}
	
	if(lstat(argv[1], &s) < 0)
	{
		printf( "lstat error\n ");
		exit(2);
	}
	
	if(!S_ISDIR(s.st_mode))
	{
		printf( "%s is not a dir name\n ", argv[1]);
		exit(3);
	}
	
	printf("\n++++++[Directory] %s is Directory\n", argv[1]);
	
	do_search_dir(argv[1]); 
	
	printf("++++++global count:   %d   files\n ", global_count);
	
	exit(0);
} 

编译并执行


$ gcc dir2.c -o dir2 -m32
$ ./dir2 version/

++++++[Directory] version/ is Directory

[File] version.tar.gz; path: version//version.tar.gz
Owner ID: 1000,Group ID: 1000
Last Access Time: Tue May 10 18:57:43 2016
Last Modification Time: Tue May 10 18:57:43 2016
Last Status Change Time: Tue May 10 18:57:43 2016

[File] version.h; path: version//version.h
Owner ID: 1000,Group ID: 1000
Last Access Time: Tue May 10 18:44:08 2016
Last Modification Time: Tue May 10 18:41:24 2016
Last Status Change Time: Tue May 10 18:42:08 2016

[File] main.c; path: version//main.c
Owner ID: 1000,Group ID: 1000
Last Access Time: Tue May 10 18:44:08 2016
Last Modification Time: Tue May 10 18:43:12 2016
Last Status Change Time: Tue May 10 18:43:12 2016

[File] version.c; path: version//version.c
Owner ID: 1000,Group ID: 1000
Last Access Time: Tue May 10 18:44:08 2016
Last Modification Time: Tue May 10 18:41:24 2016
Last Status Change Time: Tue May 10 18:42:08 2016

[File] Makefile; path: version//Makefile
Owner ID: 1000,Group ID: 1000
Last Access Time: Tue May 10 18:44:08 2016
Last Modification Time: Tue May 10 18:44:05 2016
Last Status Change Time: Tue May 10 18:44:05 2016
^^^^^^[Directory] version/ local count:   5   files
++++++global count:   5   files

POSIX淘汰接口

因为asctime, ctime, gmtime, localtime, mktime, asctime_r, ctime_r, gmtime_r, localtime_r都是日期时间转换API函数,其中POSIX.1-2008废弃了asctime(), asctime_r(), ctime(), and ctime_r(),所以64位系统上,这些函数将会产生segfault,需要采用gcc -m32来编译链接32位的库。

注:详细信息可以采用man ctime来查询。

POSIX.1-2001.   C89  and  C99  specify  asctime(),  ctime(),  gmtime(),  localtime(), and mktime().  POSIX.1-2008 marks asctime(), asctime_r(), ctime(), and ctime_r() as obsolete, recommending the use of strftime(3) instead.

所以dir2.c需要采用gcc的-m32来编译,否则将会出现如下问题:

$ gcc dir2.c -o dir2
$ ./dir2 version/

++++++[Directory] version/ is Directory

[File] version.tar.gz; path: version//version.tar.gz
Owner ID: 1000,Group ID: 1000
Segmentation fault




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值