今日阅读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. vue使用echarts引入离线地图(geo.json)并切换省市(以四川为例)

    https://blog.csdn.net/weixin_43374193/article/details/95594419 https://blog.csdn.net/harrisonz8/arti ...

  2. 含辞未吐,声若幽兰,史上最强免费人工智能AI语音合成TTS服务微软Azure(Python3.10接入)

    所谓文无第一,武无第二,云原生人工智能技术目前呈现三足鼎立的态势,微软,谷歌以及亚马逊三大巨头各擅胜场,不分伯仲,但目前微软Azure平台不仅仅只是一个PaaS平台,相比AWS,以及GAE,它应该是目 ...

  3. JavaWeb项目编译前后的目录结构

    JavaWeb项目编译前后的目录结构 编译前 页面和视图都放在webapp目录下 编译后 webapps WEB-INF

  4. 软件安装——tortoiseGit安装和配置

    Tortoisegit安装指南 TortoiseGit是一个开放的Git版本控制系统的源客户端,它是Git和Windows资源管理器的整合,提供了Git的图形化操作界面 一.软件安装 1.进入tort ...

  5. iOS14新特性

    6月23日凌晨,苹果首次在线上举办全球开发者大会WWDC2020.在大会上,苹果对iOS.iPadOS.macOS.watchOS.tvOS进行更新,其中大家最关心的iOS14,主要更新了36个功能. ...

  6. LeetCode-343. 整数拆分 - 题解分析

    题目来源 343. 整数拆分 题目详情 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化. 返回 你可以获得的最大乘积 . 示例 1: 输入: ...

  7. 三种循环的区别-break语句

    三种循环的区别 循环语句的区别 for 和 while 的小区别: 控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继 续使用,如果你想继续使用,就用w ...

  8. 行为型模式 - 责任链模式Chain of Responsibility

    我就想知道我又哪里有广告植入了,告诉我. 学习而来,代码是自己敲的.也有些自己的理解在里边,有问题希望大家指出. 模式的定义与特点 责任链(Chain of Responsibility)模式的定义: ...

  9. 一键部署nfs、rsync、sersync

    一键部署nfs.rsync.sersync 项目代码: 链接:https://pan.baidu.com/s/13I0BBAYsdK-KmPekZ5VpdA 提取码:u2tw --来自百度网盘超级会员 ...

  10. SpringBoot 三大开发工具,你都用过么?

    本文已经收录到Github仓库,该仓库包含计算机基础.Java基础.多线程.JVM.数据库.Redis.Spring.Mybatis.SpringMVC.SpringBoot.分布式.微服务.设计模式 ...