您的位置:首页 > 运维架构 > Linux

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

2016-05-25 17:32 706 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: