Linux下C语言实现文件遍历,支持嵌套和文件数量统计
2016-05-25 17:32
706 查看
Linux命令行下有两个非常基本的命令,一个是ls,一个是tree,其分别能够列出当前目录下的文件和树形方式嵌套显示目录结构。
因为网络上有很多版本的文件遍历代码,代码都没有整理过,看起来也很累,这里正好有点时间汇总整理下,并做一个练习。
同时,对一些POSIX淘汰接口进行一些解释,来帮助大家了解为什么有的代码会segfault。
#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
#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
注:详细信息可以采用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
因为网络上有很多版本的文件遍历代码,代码都没有整理过,看起来也很累,这里正好有点时间汇总整理下,并做一个练习。
同时,对一些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
相关文章推荐
- linux内核demo
- yum 安装对应内核版本的kernel-devel
- HTML5 websocket linux/c server
- 图解Linux命令实例
- 使用userdel命令删除Linux用户
- yum下载对应内核版本的kernel-devel
- linux 查找文件与进程常用命令
- Linux常用命令集合——来自朱老师
- Linux Backdoor-L3m0n · 2016/05/16 10:23
- Linux CentOS 7 安装字体库 & 中文字体
- Linux CentOS 7 安装字体库 & 中文字体
- Linux进程通信例子
- 《Linux内核设计与实现》CHAPTER13阅读梳理
- linux 环境下开发 常用指令
- Linux主线程接收数据,子线程分别对其操作后输出
- 配置 linux 开机运行脚本 && setuid & setgid
- Linux 网桥配置命令:brctl
- linux下 putty 的痛苦编译之路
- Linux 下十大命令行下载工具
- CENTOS7 安装mantis