八、Linux编程之递归遍历目录

2023-11-13

八、Linux编程之递归遍历目录


一、步骤分析

实现终端指令 ls -R,即将所有内部的目录最终展开成文件,目录的目录…所有目录最终展开,并打印相应文件的大小
在这里插入图片描述
步骤
1. 判断命令行参数,获取用户要查询的目录名,通过 int argc, char *argv[] 获取,若 argc == 1,那么用户想要查询的是当前目录 ./
2. 判断用户指定的路径是否为一个目录,通过 stat() 和宏函数 S_ISDIR() 判断
3. 如果是一个目录,打开、读取、关闭:opendir()readdir()closedir(),如果是文件,打印
4. 继续判断是否存在目录,通过 stat() 和宏函数 S_ISDIR() 判断,拼接所访问目录的绝对路径:通过函数 sprintf()strcut(),获得原路径/内部目录,回到步骤 3


二、isFile()函数

先定义一个函数 void isFile(char *name){...},用于判断是目录还是普通文件,如果是普通文件,就直接打印文件名文件大小,如果是目录文件就需要进一步操作

void isFile(char *name);

// 判断文件类型
void isFile(char *name)
{
    struct stat sbuf;
    int ret = stat(name, &sbuf);
    // 出错判断
    if(ret == -1)
    {
        perror("stat error");
        exit(1);
    }

	// 宏函数判断
    if(S_ISDIR(sbuf.st_mode))
    {
        isDir(name); // 如果是一个目录,就需要进行目录相关操作
    }else
    {
        printf("%s\t\t%ld\n", name, sbuf.st_size); // 如果是普通文件,就直接打印
    }
    
}

三、isDir()函数

定义函数 void isDir(char *name){...},当所判断的文件是目录时,就需要调用该函数,进一步操作和判断,如:打开、读取、关闭目录,并判断目录内是否还有目录

由于 readdir() 读取后只有文件名,只有文件名没有路径无法正常访问文件,我们需要将路径拼接到它的前面,调用 sprintf() 函数,这个函数与 printf() 类似,只不过 printf() 是默认打印到 stdin 文件上,而 sprintf() 打印到一个字符串上

包含头文件

#include <stdio.h>

int sprintf(char *str, const char *format, …);

将格式化输出内容打印到 char *str

char *str 传出参数
const char *format 类似 printf() 中的格式化输出,例:sprintf(out, "%s是%s", a, b);
返回值 成功时返回写入的字符大小

此外,readdir() 函数还会把 ... 也读出,如下图所示:为了防止重复循环遍历,需要把 ... 过滤掉
在这里插入图片描述
方法如下

if(strcmp(sdp->d_name, ".") == 0 || strcmp(sdp->d_name, "..") == 0)
        {
            continue;
        }

void isDir(char *name){...} 函数代码如下

void isDir(char *);

// 如果是一个目录,打开目录
void isDir(char *dir)
{
    struct dirent *sdp;
    // Linux规定路径长度不能超过256
    char path[256];

    DIR *dp = opendir(dir); // 打开目录
    if(dp == NULL)
    {
        perror("opendir error");
        return;
    }

    while((sdp = readdir(dp)) != NULL) // 读目录
    {
        // 由于readdir会把 . 和 .. 也读出来,因此需要过滤
        if(strcmp(sdp->d_name, ".") == 0 || strcmp(sdp->d_name, "..") == 0)
        {
            continue;
        }

		// 字符串拼接
        sprintf(path, "%s/%s", dir, sdp->d_name);
        /* 
        	调用 isFile() 函数,判断是否为普通文件
        	如果是普通文件,则打印
        	如果是目录文件,则继续迭代
        */
        isFile(path);
    }
    printf("\n");

    int ret = closedir(dp);
    if(ret == -1)
    {
        perror("closedir error");
        return;
    }
}

四、main()主函数

如果 int argc == 1 说明没有指定目录,默认为当前目录

int main(int argc, char *argv[])
{
    if(argc == 1)
    {
        isFile(".");
    }else
    {
        isFile(argv[1]);
    }

    return 0;
}

五、运行效果

在这里插入图片描述


六、补充要点

注意:上述内容并不完整,因为命令 ls -R 是可以指定多个目录的,因此我们需要将 main() 函数做微调:

int main(int argc, char *argv[])
{
    if(argc == 1)
    {
        isFile(".");
    }else
    {
        while(--argc)
        {
            isFile(*++argv);
        }
    }

    return 0;
}

其中,while(--argc) 表示每次访问一个目录前就让 argc1,以此来统计用户输入目录的个数

其次,isFile(*++argv); 表示每次执行前先让 argv++,再取内容,那么每次循环时 isFile(*++argv); 代表的内容分别是:
isFile(argv[1]);isFile(argv[2]);isFile(argv[3]); … … 如此类推,这样就可以对每个目录进行判断了

while(--argc)
        {
            isFile(*++argv);
        }

在这里插入图片描述


七、源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

// 函数声明
void isDir(char *);
void isFile(char *);

// 如果是一个目录,打开目录
void isDir(char *dir)
{
    struct dirent *sdp;
    // Linux规定路径长度不能超过256
    char path[256];

    DIR *dp = opendir(dir); // 打开目录
    if(dp == NULL)
    {
        perror("opendir error");
        return;
    }

    while((sdp = readdir(dp)) != NULL) // 读目录
    {
        // 由于readdir会把 . 和 .. 也读出来,因此需要过滤
        if(strcmp(sdp->d_name, ".") == 0 || strcmp(sdp->d_name, "..") == 0)
        {
            continue;
        }

		// 字符串拼接
        sprintf(path, "%s/%s", dir, sdp->d_name);
        /* 
        	调用 isFile() 函数,判断是否为普通文件
        	如果是普通文件,则打印
        	如果是目录文件,则继续迭代
        */
        isFile(path);
    }
    printf("\n");

    int ret = closedir(dp);
    if(ret == -1)
    {
        perror("closedir error");
        return;
    }
}

// 判断文件类型
void isFile(char *name)
{
    struct stat sbuf;
    int ret = stat(name, &sbuf); // 获取文件属性,判断文件类型
    // 出错判断
    if(ret == -1)
    {
        perror("stat error");
        exit(1);
    }

	// 宏函数判断是否为目录
    if(S_ISDIR(sbuf.st_mode))
    {
        isDir(name); // 如果是一个目录,就需要进行目录相关操作
    }else
    {
        printf("%s\t\t%ld\n", name, sbuf.st_size); // 如果是普通文件,就直接打印
    }
    
}

int main(int argc, char *argv[])
{
	// 判断命令行参数
    if(argc == 1)
    {
        isFile(".");
    }else
    {	// 处理用户输入的一个或多个目录
        while(--argc)
        {
            isFile(*++argv);
        }
    }

    return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

八、Linux编程之递归遍历目录 的相关文章

  • Tomcat Intellij Idea:远程部署

    RackSpace 云服务器 Ubuntu 12 04 Intellij Idea 11 1 2 Windows 8 Tomcat 7 0 26 JDK 6 在 Intellij Idea 上 当我尝试在远程 Tomcat 7 服务器上运行
  • 批量删除文件名中包含 BASH 中特殊字符的子字符串

    我的目录中有一个文件列表 opencv calib3d so2410 so opencv contrib so2410 so opencv core so2410 so opencv features2d so2410 so opencv
  • 在 C 中使用单个消息队列是否可以实现双向通信

    我希望服务器向客户端发送一些消息 并让客户端确认它 我被分配了这个任务 我可以在 C linux 中使用单个消息队列来完成它还是我需要创建两个 谢谢 是的 可以使用 sysV 消息队列来做到这一点 从您之前的问题来看 您正在使用该队列 您可
  • docker 非 root 绑定安装权限,WITH --userns-remap

    all 尝试让绑定安装权限正常工作 我的目标是在容器中绑定安装卷 以便 a 容器不以 root 用户身份运行入口点 二 docker daemon 配置了 userns remap 这样容器 主机上没有 root c 我可以绑定挂载和读 写
  • 如何为 Linux 桌面条目文件指定带有相对路径的图标?

    对于我的一个 Linux 应用程序 我有应用程序二进制文件 一个 launcher sh 脚本 针对 LD LIBRARY PATH 和一个 desktop 文件 所有这些都位于同一文件夹中 我想使用图标的相对路径而不是绝对路径 我试过了
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • tcpdump 是否受 iptables 过滤影响?

    如果我的开发机器有iptables规则到FORWARD一些数据包 这些数据包是否被 tcpdump 捕获 我有这个问题 因为我知道存在其他链称为INPUT如果数据包路由到 它会过滤发往应用程序的数据包FORWARD链 它会到达吗tcpdum
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 如何获取 (Linux) 机器的 IP 地址?

    这个问题和之前问的几乎一样如何获取本地计算机的IP地址 https stackoverflow com questions 122208 get the ip address of local computer 问题 但是我需要找到一个的I
  • 从 Xlib 转换为 xcb

    我目前正在将我的一个应用程序从 Xlib 移植到 libxcb 但在查找有关我有时使用的 XInput2 扩展的信息时遇到了一些麻烦 libxcb 中有 XInput2 实现吗 如果是的话 在哪里可以找到文档 目前我在使用此功能时遇到问题
  • 静态方法的 Java 内存模型

    我来自操作系统和 C 语言背景 在代码编译时 世界很简单 需要处理和理解堆栈 堆文本部分等 当我开始学习 Java 时 我确实了解 JVM 和垃圾收集器 我对静态方法感到很有趣 根据我的理解 类的所有实例都会在堆中创建 然后被清理 但是 对
  • C修改printf()输出到文件

    有没有办法修改printf为了将字符串输出到文件而不是控制台 我尝试在互联网上查找一些内容 发现了类似的电话dup dup2 and fflush这可能与此有关 EDIT 也许我不清楚 问题是这是C考试问题 问题如下 解释一个通常将字符串输
  • 绕过 dev/urandom|random 进行测试

    我想编写一个功能测试用例 用已知的随机数值来测试程序 我已经在单元测试期间用模拟对其进行了测试 但我也希望用于功能测试 当然不是全部 最简单的方法是什么 dev urandom仅覆盖一个进程 有没有办法做类似的事情chroot对于单个文件并
  • linux下如何从文本文件中获取值

    我有一些文本格式的文件 xxx conf 我在这个文件中有一些文本 disablelog 1 当我使用 grep r disablelog oscam conf 输出是 disablelog 1 但我只需要值1 请问你有什么想法吗 一种方法
  • 如何使用Android获取Linux内核的版本?

    如何在 Android 应用程序中获取 Linux 内核的版本 不是 100 确定 但我认为调用 uname r 需要 root 访问权限 无论如何 有一种不太肮脏的方法可以做到这一点 那就是 System getProperty os v
  • Apache 访问 Linux 中的 NTFS 链接文件夹

    在 Debian jessie 中使用 Apache2 PHP 当我想在 Apache 的文档文件夹 var www 中创建一个新的小节时 我只需创建一个指向我的 php 文件所在的外部文件夹的链接 然后只需更改该文件夹的所有者和权限文件夹
  • 这种文件锁定方法可以接受吗?

    我们有 10 个 Linux 机器 每周必须运行 100 个不同的任务 这些计算机主要在我们晚上在家时执行这些任务 我的一位同事正在开发一个项目 通过使用 Python 自动启动任务来优化运行时间 他的程序将读取任务列表 抓取一个打开的任务
  • cdc_acm:无法设置 dtr/rts - 无法与 USB cdc 设备通信

    我试图使用 pic24fj128gb206 枚举 usb cdc 设备 设备似乎已正确枚举 但是当我将设备连接到 Linux PC 时 我从内核收到以下警告消息 cdc acm 1 8 1 6 7 1 0 failed to set dtr
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • ansible unarchive 模块如何查找 tar 二进制文件?

    我正在尝试执行一个 ansible 剧本 该剧本的任务是利用unarchive模块 因为我是在 OSX 上执行此操作 所以我需要使用它gnu tar 而不是bsd tar通常与 OSX 一起提供 因为BSD tar 不受官方支持 https

随机推荐

  • XGBoost-工程实现与优缺点(中)

    工程实现 块结构设计 我们知道 决策树的学习最耗时的一个步骤就是在每次寻找最佳分裂点是都需要对特征的值进行排序 而 XGBoost 在训练之前对根据特征对数据进行了排序 然后保存到块结构中 并在每个块结构中都采用了稀疏矩阵存储格式 Comp
  • 为什么MVC不是一种设计模式

    比较Backbone和Ext4 x在MVC实现上的差异 大漠穷秋 前言 圣人云 不想做妈咪的小姐不是好码农 每一个码农的心中都有一个终极理想 那就是有一天不用再Coding 在成为妈咪的道路上 设计模式 被认为是一项必备的技能 因此 经常有
  • python sys.path.append()和sys.path.insert()的作用与区别

    python程序中使用 import XXX 时 python解析器会在当前目录 已安装和第三方模块中搜索 xxx 如果都搜索不到就会报错 使用sys path append 方法可以临时添加搜索路径 方便更简洁的import其他包和模块
  • Eclipes下载并且导入GitHub中的maven项目

    第一步 确保eclipse装有git和maven插件 最新的eclipse不需要下载应该都集成了这些基本的功能 如果没有这两个插件自己下载安装 第二步 下载GitHub项目 拷贝想要下载的项目URL eclipse gt gt gt Fil
  • C#调用C++封装的SDK库(dll动态库)——下

    C 调用C 封装的SDK库 dll动态库 下 一 说明 上一篇我们相当于封装的是C语言风格的动态dll库 供C 来调用的 C 调用C 封装的SDK库 dll动态库 上 如果我们要封装的是下面的类呢 我们该怎么办 大家先思考下 class C
  • Excel中的VLOOKUP函数

    这几天开始刷计算机二级Office的题库 怎么说呢 遇到了很多之前根本就不知道的函数 并且感觉很有用 所以想把一些考试频繁要考的 同时也是很实用的函数一点一点的记下来 今天我来谈一下在Excel里面的一个查找函数 VLOOKUP函数 这个函
  • 小小程序员预备上路

    2011正式接触代码 进入CSDN乐知学院PHP方向 这篇博客便是我所有的成长的见证 至今 大大小小的项目做过不少 项目中学会了很多 怎么与小组默契配合 提高效率 大一第一次的项目 纯HTML静态网页 班级40个人5人一小组 总共8组 稀里
  • 手机投屏不是全屏怎么办_手机投屏怎么满屏

    手机投屏是很多小伙伴们都喜欢玩的 不少小伙伴们小伙伴们在使用手机投屏的时候发现不能满屏 想要知道方法的小伙伴们 就让小编给大家详细的讲讲满屏方法吧 手机投屏怎么满屏 1 手机具有投屏的功能 目前大多数手机都已经具备发无线投屏的功能 2 电视
  • Linux 部署 Mycat 实现 MariaDB 分库分表

    安装请参照Mycat 实现 Mysql 集群读写分离 高飞的博客 CSDN博客MySQL 读写分离的概述https blog csdn net gaofei0428 article details 117503469 spm 1001 20
  • 【Stable Diffusion】安装过程中常见报错解决方法

    转自 https openai wiki stable diffusion error html 如何查看报错 在你安装时可能经常遇到各种各样的问题 但是对于一堆陌生的英文和各种各样的错误 大家可能经常无从下手 下面我将会教大家如何查看报错
  • SQL Server研习录(29)——sql server 设置列自增长

    SQL Server研习录 29 sql server 设置列自增长 版权声明 一 设置列自增长 1 创建表时 2 创建表后 版权声明 本文原创作者 清风不渡 博客地址 https blog csdn net WXKKang 一 设置列自增
  • kali Linux2021安装VMwareTools更新源(详解)

    VMwareTools安装 1 点击虚拟机设置 点击安装VMwareTools 2 打开kali进入界面 双击界面中的VMwareTools 3 进入界面中VMwareTools所在文件中复制压缩包到 目录中的tmp里 4 在tmp中打开终
  • 基于 Android 13 的 Activity 启动流程分析

    对于 Android 客户端开发者来说 Activity 是我们再熟悉不过的一个组件了 它是 Android 四大组件之一 是一个用于直接与用户交互的展示型 UI 组件 在开发过程中 启动并创建一个 Activity 流程非常简单 而在系统
  • 平面二维任意椭圆数据拟合算法推导及程序实现详解

    在刚刚过去的2017全国大学生数学建模比赛中 笔者有幸指导了一组本科学生参赛 对于赛题A CT系统参数标定及成像 中的CT系统参数标定 经过将问题进一步的提炼 问题最终变成了在平面二维空间中对任意椭圆进行拟合的问题 笔者花了大概四个小时的时
  • 战斗系统设计

    战斗设计 战斗技能 技能分类 普通攻击 被动技能 1 战斗开始时 2 间隔N次普攻后触发 3 阵亡时 4 生命低于x 触发 5 概率触发 优先级最低 6 替换普攻 7 有FindTargetRange单位靠近自身N米时触发 主动技能 属性技
  • 微信小程序text控件部分字体文字大小和颜色设置四

    在我们android中有的时候会要求textview控件显示文字部分颜色不同而且大小也不同 这个在微信小程序中怎么做呢 因为在微信小程序中所有的显示都是通过标签来实现的 那么标签时可以嵌套的 比如显示hello world 要求hello颜
  • Qt下使用DbgHelp和SetUnhandledExceptionFilter来获取Crash log/dump文件

    第一步 在pro中链接Lib LIBS lDbgHelp 第二步 在main源文件中添加 include
  • 计算机自顶向下WireShark实验2:DNS

    前言 本博客仅记录我自己做实验所用 在码云上看到一份比较好的自顶向下的实验记录 大家可以参考计算机自顶向下实验 实验内容 1 运行nslookup获取亚洲一个Web服务器的IP地址 那台服务器的IP地址是什么 答 对自己的学校采用即可 2
  • win10下web漏洞扫描工具:AWVS安装教程

    01 AWVS安装 windows上安装其实很简单 以安装AWVS12版本为例子 具体步骤如下 01 双击exe安装 02 点击 Next 03 选择我同意 04 设置用户名和密码 这里用户名是以邮箱为准的 密码需要复杂点 不然会提示密码太
  • 八、Linux编程之递归遍历目录

    八 Linux编程之递归遍历目录 目录 八 Linux编程之递归遍历目录 一 步骤分析 二 isFile 函数 三 isDir 函数 int sprintf char str const char format 四 main 主函数 五 运