题目如下:
实现linux下tree的单一功能[只打印目录个数和文件个数(不包含隐藏文件)]
首选我们介绍几个相关的linux 系统API
函数名 | 函数描述 | 函数声明 |
opendir | 打开一个目录,成功返回一个DIR*类型指针,失败返回NULL | DIR* opendir(const char* name) |
readdir | 读取打开的目录下的子成员,成功返回结构体指针,否则返回NULL | struct dirent* readdir(DIR* dir) |
closedir | 关闭已打开的目录.成功返回0,失败返回-1 | int closedir(DIR* dirp) |
struct dirent 结构体 #include <dirent.h> //所需要包含头文件 struct dirent{ ino_t d_ino; //索引[inode]编号 off_t d_off; //在目录文件中的偏移 unsigned short d_reclen; //文件名长度 unsigned char d_type; //文件类型 char d_name[256]; //文件名 } d_type 应对的所有文件类型 DT_BLK 块设备 DT_CHR 字符设备 DT_DIR 目录 DT_FIFO 有名管道 DT_LNK 符号链接(软链接) DT_REG 普通文件 DT_SOCK socket套接字 DT_UNKNOWN 未知类型 |
注意事项:
l.linux目录下有 . 和 .. 分别代表指向当前目录和上一级目录,不处理会造成死循环
2. 不包含隐藏文件,需要将普通文件以.开头的以忽略处理
代码如下:
#include <stdio.h> //输入输出头文件
#include <stdlib.h> //eixt()函数头文件
#include <unistd.h> //unix标准库头文件
#include <sys/types.h> //opendir() closedir() readdir()所需头文件
#include <dirent.h> //同上
#include <string.h> //字符串常用API头文件
//功能函数
//成功返回EXIT_SUCCESS
//失败返回EXIT_FAILURE
int myTree(const char* root, unsigned int* const dirs, unsigned int* const files){
int ret = EXIT_SUCCESS; //返回值
DIR* dir = NULL; //打开的目录
char path[1024] = { 0 }; //拼接文件相对路径使用
struct dirent* ptr = NULL; //读取的目录下子成员结构体
//判断参数
if(NULL == root || NULL == dirs || NULL == files){
//错误提示
printf("func %s err:[NULL == root || NULL == dirs || NULL == files]", __FUNCTION__);
//直接退出
ret = EXIT_FAILURE;
goto END;
}
//打开目录
dir = opendir(root);
//判断是否打开失败
if(NULL == dir){
//友情错误提示
perror("func tree->opendir error: ");
ret = EXIT_FAILURE;
goto END;
}
//循环遍历目录下的文件成员
while(NULL != (ptr = readdir(dir))){
//判断是否是 . 和 .. 目录,或.开头的隐藏文件
if(0 == strncmp(ptr->d_name, ".", 1) || 0 == strcmp(ptr->d_name, "..")){
continue; //跳过处理
}
//如果是目录
if(DT_DIR == ptr->d_type){
(*dirs)++; //目录个数+1
sprintf(path, "%s/%s", root, ptr->d_name);
myTree(path, dirs, files);
}else{
(*files)++;
}
}
END:
//判断目录是否已关闭
if(NULL != dir){
closedir(dir);
dir = NULL;
}
return ret;
}
//主函数
int main(int argc, char* argv[]){
unsigned int dirs = 0; // 统计目录个数
unsigned int files = 0; // 统计文件个数
//判断命令行参数
if(2 > argc){
//没有参数,默认统计当前目录下
myTree(".", &dirs, &files);
}
else{
int i = 0;
//多个参数的情况下
for(i = 1; i < argc; i++){
myTree(argv[i], &dirs, &files);
}
}
//输出最后统计信息
printf("%d directories, %d files\n", dirs, files);
return EXIT_SUCCESS;
}