今日阅读Linux程序设计第四版时,书中给出了一段实例代码,功能为实现/home目录下各级目录结构,当然不一定非得是/home下目录才可以,任何一级目录都可以。



自己尝试在Ubuntu系统运行编译,实现效果如下:



自己对该程序各行代码进行一个解读分析,同时查阅各项资料:

首先定义打印目录的函数

void printdir(char *dir ,int depth)

char *dir代表DIR目录名,int depth设置当前目录打印后所占空格位置

接下来定义函数内需要的三项参数

  DIR *dp;              /*申请一个目录指针*/
struct dirent *entry;/*申请一个结构体指针,该结构体包含目录和文件信息*/
struct stat statbuf; /*申请一个结构体,该结构体用于之后各级目录内文件访问权限的判定*/

通过查阅资料:

该部分中DIR,dirent和stat经常相互配合和使用。

DIR结构体是一个目录流指针,用于完成各项目录操作

dirent则类比于一个一个接受DIR指针传来目录,并将这个目录进一步细分化,引导到stat当中的中间站

stat则储存着各项目录内具体的文件信息

三者是一种递进的关系

接下来对输入参数有效性进行判断

if((dp = opendir(dir)) == NULL){ /*函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针*/
fprintf(stderr,"cannot open directory: %s\n",dir);
return;
} /*如果无法打开该目录,则直接打印该层目录信息*/ chdir(dir); /*chdir(const char * path)用于把当前工作目录更改为参数路径指示目录*/

该部分主要完成从目录到目录指针,以及判定是否为目录的操作

DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针

最后进行打印目录操作:

while((entry = readdir(dp)) != NULL){

    lstat(entry->d_name,&statbuf);      /* 该步骤将相关文件路径名字对应的文件结构体放入stat结构中 */

    if(S_ISDIR(statbuf.st_mode)){       /* S_ISDIR宏用于判断传入参数是否是一个目录 */

      if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)/*如果到达根目录或者路径名为.,则跳过去该部分*/
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
/* 假如depth等于5,可类比为:printf("%5s%s/\n","",entry->d_name) 此处留出depth的空格来,随后写入目录对应的文件名,然后另起一行 */
printdir(entry->d_name,depth+4);
}
else printf("%*s%s\n",depth,"",entry->d_name);
}/*该部分用于逐级循环,自上而下读入目录,返回各级目录指针*/ chdir("..");
closedir(dp);

具体部分功能已经标注,另外说明:

printf("%*s%s/\n",depth,"",entry->d_name)

该函数中%*s的※号代表接受后面的一个int参数变量,假设当前depth等于5,则类比为printf("%5s%s/\n","",entry->d_name) ,意思是先空出5个空格来,再进行目录打印。

为什么需要这样子?

因为目录在没完成单个文件名打印后需要另起一行,但是级别更加靠近根节点目录理应更加靠前,反之需要靠后。



该部分采用了递归方法:

printf("%*s%s/\n",depth,"",entry->d_name);
/* 假如depth等于5,可类比为:printf("%5s%s/\n","",entry->d_name) 此处留出depth的空格来,随后写入目录对应的文件名,然后另起一行 */
printdir(entry->d_name,depth+4);
}
else printf("%*s%s\n",depth,"",entry->d_name);
}/*该部分用于逐级循环,自上而下读入目录,返回各级目录指针*/

所以在每一层可以保留自己所在层的需要空出来的depth具体值。

全部代码如下:

#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h> void printdir(char *dir ,int depth)
{
DIR *dp; /*申请一个目录指针*/
struct dirent *entry;/*申请一个结构体指针,该结构体包含目录和文件信息*/
struct stat statbuf; /*申请一个结构体,该结构体用于之后各级目录内文件访问权限的判定*/ if((dp = opendir(dir)) == NULL){ /*函数 DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针*/
fprintf(stderr,"cannot open directory: %s\n",dir);
return;
} /*如果无法打开该目录,则直接打印该层目录信息*/ chdir(dir); /*chdir(const char * path)用于把当前工作目录更改为参数路径指示目录*/ while((entry = readdir(dp)) != NULL){ lstat(entry->d_name,&statbuf); /* 该步骤将相关文件路径名字对应的文件结构体放入stat结构中 */ if(S_ISDIR(statbuf.st_mode)){ /* S_ISDIR宏用于判断传入参数是否是一个目录 */ if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)/*如果到达根目录或者路径名为.,则跳过去该部分*/
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
/* 假如depth等于5,可类比为:printf("%5s%s/\n","",entry->d_name) 此处留出depth的空格来,随后写入目录对应的文件名,然后另起一行 */
printdir(entry->d_name,depth+4);
}
else printf("%*s%s\n",depth,"",entry->d_name);
}/*该部分用于逐级循环,自上而下读入目录,返回各级目录指针*/ chdir("..");
closedir(dp);
} int main()
{
printf("Directory scan of /home:\n");
printdir("/home",0);
printf("done.\n"); exit(0);
}

在Linux中实现打印目录程序遇到问题及解决的更多相关文章

  1. 在Linux中运行Nancy应用程序

    最近在研究如何将.NET应用程序移植到非Windows操作系统中运行,逐渐会写一些文章出来.目前还没有太深的研究,所以这些文章大多主要是记录我的一些实验. 这篇文章记录了我如何利用NancyFx编写一 ...

  2. [转]Linux中文件权限目录权限的意义及权限对文件目录的意义

    转自:http://www.jb51.net/article/77458.htm linux中目录与文件权限的意义 一.文件权限的意义 r:可以读这个文件的具体内容: w:可以编辑这个文件的内容,包括 ...

  3. 限制SSH用户访问Linux中指定的目录

    限制SSH用户访问Linux中指定的目录 http://os.51cto.com/art/201703/534895.htm#topx http://www.cnblogs.com/lykyl/arc ...

  4. linux中的重要目录

    1./boot 引导程序,内核的存放的目录. 此目录,包含了在引导过程中所必须的文件,引导程序的相关文件(如:grub,lilo以及相应的配置文件及linux操作系统内核相关文件). 2./sbin/ ...

  5. 【转】完美解读Linux中文件系统的目录结构

    一.前 言 接触Linux也有一段时间了,不过这几天在编译开源程序时,才发现自己对linux文件系统的目录结构了解的不够透彻,很多重要目录都说不清楚是用来干嘛的,于是在网上百度了一下这方面的介绍,根据 ...

  6. linux中VI编写C程序。。。

    在linux中编写C程序时不像编写shell那样开头要#!/bin/bash,但是在C程序中要指定头文件(头文件是指输入输出,宏等,而且要首先声明,也是必须要开始就声明的) 写好C代码后要给C文件赋予 ...

  7. linux中rc.d目录下的文件

    参考 http://blog.sina.com.cn/s/blog_414d78870102vqj5.html http://www.360doc.com/content/12/0820/17/933 ...

  8. Linux中Too many open files 问题分析和解决

    今天某个服务的日志中出现了大量的异常: [WARN ] 2018-06-15 16:55:20,831 --New I/O server boss #1 ([id: 0x55007b59, /0.0. ...

  9. Windows转到linux中,文件乱码,文件编码转换 & 解决sqlplus连接oracle乱码

    转载:http://www.cnblogs.com/wanyao/p/3399269.html 最近,学习又重新开始Linux学习,所以一直在Centos中,昨天一朋友把他在Windows下写的C程序 ...

  10. Linux中syntax error near unexpected token 错误提示解决方法

    Linux中syntax error near unexpected token ... 错误提示有一般有两种原因: 1)window和Linux下换行符不一致导致 window下的换行和Linux下 ...

随机推荐

  1. [OpenCV实战]25 使用OpenCV进行泊松克隆

    目录 1 Seamless Cloning实现 1.1 Seamless Cloning实例 1.2 正常克隆(NORMAL_CLONE)与混合克隆(MIXED_CLONE) 1.2.1 Normal ...

  2. (数据科学学习手札148)geopandas直接支持gdb文件写出与追加

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,在我之前的某篇文章中为大家介绍 ...

  3. 算法学习笔记(5): 最近公共祖先(LCA)

    最近公共祖先(LCA) 目录 最近公共祖先(LCA) 定义 求法 方法一:树上倍增 朴素算法 复杂度分析 方法二:dfs序与ST表 初始化与查询 复杂度分析 方法三:树链剖分 DFS序 性质 重链 重 ...

  4. Spring Boot通过Actuator显示git和build的信息

    1 简介 为了更好的版本控制和问题定位,我们需要知道正在运行的应用是什么版本,什么时候打包的,Git的相关信息等.通过/actuator/info可以帮助我们获取这些信息. 2 配置 首先要有actu ...

  5. appium如何连接多台设备

    我们在做app自动化的时候,若要考虑兼容性问题,需要跑几台设备,要是一台一台的跑比较耗 时,因此需要考虑使用多线程来同时操作多台设备. 1.我们拿两台设备来模拟操作下,使用:adb devices查看 ...

  6. Echarts自适应屏幕,无需刷新网页,可根据屏幕大小完美展现,内有详细代码注释,我可真是个小机灵~~O(∩_∩)O哈哈~

    Echarts自适应屏幕,无需刷新网页,可根据屏幕大小完美展现 效果如图 随意拖拉,无惧检验 ~ ~ ~ ~ 下面上代码 里边有详细解释 <template> <div class= ...

  7. 12月19日内容总结——Q查询进阶、ORM查询优化、ORM事务、ORM常用字段类型和字段参数、Ajax介绍、数据编码格式、Ajax携带文件数据

    目录 一.Q查询进阶操作 二.ORM查询优化 三.ORM事务操作 四.ORM常用字段类型 五.ORM常用字段参数 六.Ajax AJAX简介 应用场景 AJAX的优点 语法实现 七.数据编码格式(Co ...

  8. 【一句话】@Configuration和@Component的区别

    首先一句话: @Configuration修饰的类会被Cglib动态代理,@Component不会. 详细: Cglib动态代理生成当前对象的子类Class,并对方法拦截,多次调用@Bean方法时直接 ...

  9. JAVA虚拟机20-基于栈的解释器执行过程示例

    1.准备代码 public int calc() { int a = 100; int b = 200; int c = 300; return (a + b) * c; } 2.使用javap -v ...

  10. springBoot集成flowable

    前言 Flowable可以十分灵活地加入你的应用/服务/构架.可以将JAR形式发布的Flowable库加入应用或服务,来嵌入引擎. 以JAR形式发布使Flowable可以轻易加入任何Java环境:Ja ...