红联Linux门户
Linux帮助

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

发布时间:2016-07-10 10:37:35来源:linux网站作者:ALAWSWF
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
 
本文永久更新地址:http://www.linuxdiyf.com/linux/22244.html