从pwd命令的实现理解ls-R的逻辑

简介: pwd命令的实现


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。


引言

  • 本文不再赘述ls命令与递归
  • ls -R在man手册中的定义为:
list subdirectories recursively

即通过递归的手段列出所有子目录

在我们为-R指定好目录后,其便会开始展示从当前目录开始,往下每一层的所有子目录,在代码实现中关于递归的部分是比较难以理解的一个点

  • pwd在man手册中的定义为:
print name of current/working directory

即打印当前工作目录

pwd命令想要实现,就需要从当前目录开始,向上遍历直至抵达当前目录的根目录,pwd命令同样可以通过递归实现

  • 区别于-R的自上向下,pwd的递归为自下向上,且pwd的实现较为简单,我们可以通过对pwd的学习来帮助我们理解-R的逻辑

pwd的逻辑

  • 追踪链接,读取目录,逐目录沿文件树向上追踪
  • 每步都记录“.”的inode号
  • 在父目录中查找记录值inode对应的名称
  • 达到树的顶端即停止
  • 逻辑细节请参见代码实现
  • 图示:

pwd的逻辑

pwd的代码实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<dirent.h>

ino_t get_inode(char *);
void printpathto(ino_t);
void inum_to_name(ino_t , char *, int );

int main()
{
    printpathto(get_inode( "." ));//打印路径
    putchar('\n');//换行
    return 0;
}

void printpathto(ino_t this_inode)
//利用inode号去递归,保存每一次记录到的文件夹名,从而得到路径
{
    ino_t    my_inode;
    char    its_name[BUFSIZ];

    if (get_inode("..") != this_inode)//this_inode的初始值参见12行
    {
        chdir("..");//利用chdir()函数跳转至父目录

        inum_to_name(this_inode,its_name,BUFSIZ);//利用inode号获取当前目录名称

        my_inode = get_inode( "." );//获取父目录inode号,更新my_node
        printpathto( my_inode );//递归
        printf("/%s", its_name );//递归至顶层,所以打印从初始目录的根目录开始,符合逻辑
    }
}

void inum_to_name(ino_t inode_to_find , char *namebuf, int buflen)
/*
在当前文件夹中找到inode号与记录值this_inode匹配的文件夹
其就是下一级目录
保存其名字到namebuf数组
*/
{
    DIR    *dir_ptr;//DIR结构体
    struct dirent *direntp;//dirent结构体

    dir_ptr = opendir(".");
    if (dir_ptr == NULL){//处理失败情况
        perror(".");
        exit(1);
    }

    //在文件夹中搜索指定的inode号
    while ((direntp = readdir(dir_ptr)) != NULL){
        if ( direntp->d_ino == inode_to_find ){
            strncpy( namebuf, direntp->d_name, buflen);
            namebuf[buflen-1] = '\0';   /* just in case */
            closedir( dir_ptr );
            return;
        }
    }
    //处理失败情况
    fprintf(stderr, "error looking for inum %ld\n", inode_to_find);
    exit(1);//程序异常终止信号
}

ino_t get_inode( char *fname )
//返回inode号
{
    struct stat info;

    if (stat(fname, &info ) == -1){
        fprintf(stderr, "Cannot stat ");
        perror(fname);
        exit(1);
    }
    return info.st_ino;
}

ls -R逻辑

此处逻辑仅为简单逻辑,具体实现细节请参看:ls实现

  1. 从指定目录开始递归(若未指定则从当前目录开始)
  2. 首先遍历展示当前目录内容,若目录内容之一为目录,则递归进入
  3. 进入执行2,执行完毕后返回父目录
  4. 遍历完所有目录的所有文件
  5. 采用尾递归

参考:

  • 《Unix/Linux编程实践教程》
目录
相关文章
|
前端开发 JavaScript UED
一看就懂的gulp操作指南:让前端工作变得更加轻松(二)
一看就懂的gulp操作指南:让前端工作变得更加轻松
|
存储 传感器 编解码
turtlebot3 在gazebo仿真下 通过 gmapping slam 建立二维平面地图——全过程
turtlebot3 在gazebo仿真下 通过 gmapping slam 建立二维平面地图——全过程
turtlebot3 在gazebo仿真下 通过 gmapping slam 建立二维平面地图——全过程
|
Oracle 关系型数据库 MySQL
centos6安装mariadb失败及解决办法
centos6安装mariadb失败及解决办法
510 4
|
SQL 数据采集 存储
Hive 判断某个字段长度
【8月更文挑战第13天】
454 2
|
SQL 关系型数据库 MySQL
MySQL Workbench的安装与配置
MySQL Workbench的安装与配置
|
开发者 Python
软件开发中的 DRY、KISS 和 SOLID 原则
**软件开发中的DRY、KISS和SOLID原则概览** - **DRY (Don&#39;t Repeat Yourself)**: 避免代码重复,确保每项知识在系统中有唯一表示,减少冗余,提高可维护性。例如,通过封装重复逻辑到函数或类。
322 0
|
监控 小程序 数据处理
揭秘支付宝小程序性能优化秘籍:从加载到运行,每一步都快人一步!
【8月更文挑战第27天】本文深入探讨了支付宝小程序性能优化的关键技术和策略,包括减少网络请求、利用CDN加速、代码按需加载、图片压缩、懒加载以及性能监控等多方面内容,并提供了实用的示例代码,帮助开发者显著提升小程序的加载速度与运行效率,创造更佳用户体验。
505 1
|
SQL 关系型数据库 MySQL
【MySQL进阶之路丨第八篇】MySQL数据的插入及查询
【MySQL进阶之路丨第八篇】MySQL数据的插入及查询
535 0
|
Kubernetes 监控 负载均衡
10个最佳的Kubernetes工具
Kubernetes生态工具整理
1492 0
10个最佳的Kubernetes工具
|
安全 调度 数据格式
1553B基础常识篇
1553B基础常识篇
2233 0
1553B基础常识篇