目录

递归实现

非递归实现


我们知道,许多操作系统中的目录结构都是使用树结构。

使用递归的方法定义树是比较容易的。一棵树地一些节点的集合。
这个集合可以为空,若非空,则树由树根和0个或者多个非空的子树组成。
子树中的根都被来自树根的一条有向的边所连接。

因此,可以很自然地想到使用递归的方式来遍历指定的目录。

除了递归,还可以考虑使用非递归方式实现,这样效率会更高,但也更复杂。

递归实现

  • 思路:递归实现较简单,对于一个给定的目录,遍历目录下所有文件,有三种情况:

    • 本目录或父目录,忽略
    • 普通文件,输出
    • 目录,递归调用
  • 源代码如下:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>#define MAX_PATH_LEN (256)static void trave_dir(char* path) {DIR *d = NULL;struct dirent *dp = NULL; /* readdir函数的返回值就存放在这个结构体中 */struct stat st;    char p[MAX_PATH_LEN] = {0};if(stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) {printf("invalid path: %s\n", path);return;}if(!(d = opendir(path))) {printf("opendir[%s] error: %m\n", path);return;}while((dp = readdir(d)) != NULL) {/* 把当前目录.,上一级目录..及隐藏文件都去掉,避免死循环遍历目录 */if((!strncmp(dp->d_name, ".", 1)) || (!strncmp(dp->d_name, "..", 2)))continue;snprintf(p, sizeof(p) - 1, "%s/%s", path, dp->d_name);stat(p, &st);if(!S_ISDIR(st.st_mode)) {printf("%s\n", dp->d_name);} else {printf("%s/\n", dp->d_name);trave_dir(p);}}closedir(d);return;
}int main(int argc, char **argv)
{   char *path = NULL;if (argc != 2) {printf("Usage: %s [dir]\n", argv[0]);printf("use DEFAULT option: %s .\n", argv[0]);printf("-------------------------------------------\n");path = "./";} else {path = argv[1];}trave_dir(path);return 0;
}

非递归实现

非递归实现的方法会有很多,一个思路是,每次遍历目录时,把查找到的文件直接输出,目录则保存,用于下次遍历目录下的内容。

此处使用链表实现,结构体用于存储目录路径和下一个目录,遍历目录的过程同上,代码如下:

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <error.h>
#include <sys/stat.h>  #define MAX_FILE_NAME_LEN 256typedef struct foldernode_t {char *path;                // point to foldername or filename pathstruct foldernode_t *next;
} foldernode;static void travel_files(char *path)
{DIR *dir;struct dirent *ptr;char foldername[MAX_FILE_NAME_LEN] = {0};char folderpath[MAX_FILE_NAME_LEN] = {0};foldernode *folderstart;folderstart = calloc(1, sizeof(foldernode));/* ignore err case */folderstart->path = calloc(1, MAX_FILE_NAME_LEN + 1); strncpy(folderstart->path, path, MAX_FILE_NAME_LEN);folderstart->next = NULL;foldernode *folderfirst = folderstart; /* use to search */foldernode *folderlast = folderstart; /* use to add foldernode */foldernode *oldfirst = NULL;while(folderfirst != NULL) {printf("dir=%s\n", folderfirst->path);if ((dir = opendir(folderfirst->path)) != NULL) {while ((ptr = readdir(dir)) != NULL) {if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {continue;  } else if (ptr->d_type == DT_REG) { /* regular file */printf("%s\n", ptr->d_name);} else if (ptr->d_type == DT_DIR) { /* dir */bzero(foldername, sizeof(foldername));bzero(folderpath, sizeof(folderpath));strncpy(foldername, ptr->d_name, sizeof(foldername));snprintf(folderpath, sizeof(folderpath), "%s/%s", folderfirst->path , foldername);printf("%s\n", folderpath);foldernode *foldernew;foldernew = calloc(1, sizeof(foldernode));foldernew->path = calloc(1, MAX_FILE_NAME_LEN + 1); strncpy(foldernew->path, folderpath, MAX_FILE_NAME_LEN);foldernew->next = NULL;folderlast->next = foldernew;folderlast = foldernew;}}} else {printf("opendir[%s] error: %m\n", folderfirst->path);return;}oldfirst = folderfirst;folderfirst = folderfirst->next; // change folderfirst point to next foldernodeif (oldfirst) {if (oldfirst->path) {free(oldfirst->path);oldfirst->path = NULL;}free(oldfirst);oldfirst = NULL;}closedir(dir);}
}int main(int argc,char **argv)
{if (argc != 2) {printf("Usage: %s path\n", argv[0]);return 0;}travel_files(argv[1]);return 0;
}

对目录的遍历是比较基本的功能,对于理解文件系统和数据结构有一定的帮助。

也可以参考bash命令中ls的源码,增加对命令行参数的支持,实现更加复杂的功能。

linux c 遍历目录 及 目录下文件相关推荐

  1. linux子目录个数,技术|如何知道目录及子目录下文件的数量

    在本指南中,我们将介绍如何在 Linux 系统上显示当前工作目录或任何目录及其子目录中的文件数量. 我们将使用 find 命令,它用于搜索目录层次结构中的文件,以及 wc 命令,它会打印每个文件或来自 ...

  2. linux重装系统怎么保存home下文件,Linux系统重装与还原

    当初第一次装ubuntu系统时,对文件系统的构成还不太了解,所以在分区的时候给home的分区特别小,导致后期软件都装不进去.说磁盘已满.所以想对系统又一次分区. 上网找了资料,都说用GParted这个 ...

  3. Linux 不小心将某目录下文件全删除了,如何恢复

    问题描述: 问题:不小心将某目录下文件全删除了,如何恢复 例如:目录 /root/app 下文件全部被误删除 root@apis:~/app# rm -rf * 解决方案: 1. cd到被删除文件的目 ...

  4. 关于linux系统遍历一个目录下所有文件的代码原理以及代码

    11.23 这段时间一直在写linux系统内核的代码,刚开始就在linux文件系统这儿纠了好久,直到现在,说不会写吧!写了好几版了,也生成exe了,说会写吧,代码一跑,哦豁,没达到自已想要的效果,就是 ...

  5. linux中的文件夹压缩文件,linux将文件拷贝到目录下Linux下文件的压缩与打包详解...

    在Linux中,有很多的压缩命令.利用这些压缩命令,可以方便的从网络上下载大型的文件.同时,我们知道,Linux文件的扩展名是没有特殊意义的,不过,因为Linux下存在着许多压缩命令,所以为了方便记忆 ...

  6. Linux中/proc目录下文件详解

    Linux中/proc目录下文件详解(一) 声明:可以自由转载本文,但请务必保留本文的完整性. 作者:张子坚 email:zhangzijian@163.com 说明:本文所涉及示例均在fedora ...

  7. Linux系统下文件与目录权限管理

    Linux文件目录权限管理 一.Linux文件属性及权限 1.Linux文件及目录权限及属性说明 (1)权限及属性说明 (2)文件权限说明 三种权限说明:r 读  read w 写  write x ...

  8. linux 检查权限,检查目录下 文件的权限-linux shell脚本,

    检查目录下 文件的权限-linux shell脚本, #!/bin/bash #History: #2019/07/23    Fsq #This Program will check Permiss ...

  9. linux各目录的文件大小,Linux下查看文件大小和目录大小以及目录下文件的大小...

    在linux中经常会查看文件大小,通常用的命令du: 该命令详细解释如下: [www@server101 logs]$ du --help 用法:du [选项]... [文件]... 或:du [选项 ...

最新文章

  1. 卷积神经网络四种卷积类型
  2. Git复习(八)之快速理解Git结构
  3. 操作系统原理: 操作系统概述
  4. MPEG4 (ISO/IEC 14496) 文档内容 简介
  5. 巨杉mysql支持临时表_sql server用变量动态命名临时表表名
  6. Connection timed out: connect; Communications link failure
  7. 初入c++(三)this指针,友元函数,友元类
  8. eclipse或Myeclipse中web项目没有run on server时怎么办?
  9. Leetcode每日一题:112.path-sum(路经总和)
  10. Android 系统定时管理器AlarmManager的使用
  11. pfSesne 使用IPv6与隧道代理
  12. SQL Server性能常用语句
  13. linux脚本中sed -i,Linux Shell 脚本之sed命令详解
  14. 数据校验简介与C/C++代码实现
  15. Discuz仿集思街淘宝客网站模板/粉色淘客模板
  16. 【毕业论文】分享当年使用过的一些好用网站,包括论文去重,翻译,作图神器,免费文献查找 | 第 1 期
  17. 联想启天m430安装黑苹果 10500 big sur 11.6
  18. 【Love2d从青铜到王者】第二篇:Love2d详细介绍以及官网安装
  19. 讯飞AIUI ubuntu linux使用
  20. Java Web概述-练习题

热门文章

  1. android中DatePickerTimePicker的应用
  2. 不喜欢冷漠,喜欢笑容、热情和拥抱
  3. ppk on JavaScript第二章:背景(完结篇)
  4. 计算机山西特岗考试题库,山西特岗历年试题
  5. python threading condition使用_Python threading模块condition原理及运行流程详解
  6. 用 Flask 来写个轻博客 (25) — 使用 Flask-Principal 实现角色权限功能
  7. 嵌入式驱动程序之信号量
  8. Java客户端访问HBase集群解决方案(优化)
  9. vSphere PowerCLI安装及命令
  10. 流程控制--for序列