今日阅读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. 快速排序算法实现 (y总课后)

    主要思路: 1.确定 边界 l----------r  (left right) 2.确定中间值  l--------x----------r 3.优雅快排: 设置两个指针i,j. i从左边开始运行 ...

  2. SQL29 计算用户的平均次日留存率

    SQL29 计算用户的平均次日留存率 困难 通过率:48.58% 时间限制:1秒 空间限制:256M 描述 题目:现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率.请你取出相应数据. 示例 ...

  3. Redis+Hbase+RocketMQ 实际使用问题案例分享

    需求 将Hbase数据,解析后推送到RocketMQ. redis使用list数据类型,存储了需要推送的数据的RowKey及表名. 简单画个流程图就是: 分析及确定方案 Redis 明确list中元素 ...

  4. 红客突击队&突击队分队

    红客突击队,于2019年,由队长k龙联合国内多位顶尖高校研究生牵头成立.其团队从成立至今多次参加国际网络安全竞赛并取得良好成绩,积累了丰富的竞赛经验.团队现有三十多位正式成员及若干预备人员,旨在打造国 ...

  5. Redefinition of 'y1' as different kind of symbol

    Redefinition of 'y1' as different kind of symbol 原因 解释:此次定义的y1变量与函数库中定义的y1重名了,所以编译错误,重定义了y1变量. 解决方法: ...

  6. P6327 区间加区间sin和 题解

    P6327 区间加区间sin和 题解 题目描述 给出一个长度为 \(n\) 的整数序列 \(a_1,a_2,\ldots,a_n\),进行 \(m\) 次操作,操作分为两类. 操作 \(1\):给出 ...

  7. 火山引擎 DataLeap:3 个关键步骤,复制字节跳动一站式数据治理经验

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,并进入官方交流群 DataLeap 是火山引擎数智平台 VeDI 旗下的大数据研发治理套件产品,帮助用户快速完成数据集成.开发.运维.治理. ...

  8. 免费的在线PS工具

    免费的在线PS工具:https://www.logosc.cn/online-ps

  9. 这是一篇乖巧的草稿——vscode上传代码到代码托管平台GitHub

    一.在GitHub上创建一个远程仓库: 以上,就创建好了一个名为pythonStudy的仓库,现在先别把它关掉,先最小化 二.安装版本管理工具git:git属于无脑安装,可以更改安装路径 打开项目文件 ...

  10. Java期末测试

    会议预约管理信息系统(50分)     1.项目背景: 会议是企业进行决策.协商的重要组织形式,是企业日常办公处理事务的重要手段,是办公流程中不可缺少的重要环节,作为企业,如何有效的进行会议组织,管理 ...