从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编程实践教程》
目录
相关文章
|
5月前
|
Linux
Linux部署 cd-pwd命令,cd 不写参数 就直接回到用户的HOME目录,pwd 查看当前的工作目录,pwd是常看当前目录的路径,无参数
Linux部署 cd-pwd命令,cd 不写参数 就直接回到用户的HOME目录,pwd 查看当前的工作目录,pwd是常看当前目录的路径,无参数
|
Shell 开发工具
写一个脚本/root/bin/sumspace.sh,传递两个文件 路径作为参数给脚本,计算这两个文件中所有空白行之和
写一个脚本/root/bin/sumspace.sh,传递两个文件 路径作为参数给脚本,计算这两个文件中所有空白行之和
78 1
|
Linux
详细介绍 `ls -ltr` 命令的功能和用法
详细介绍 `ls -ltr` 命令的功能和用法
221 1
详细介绍 `ls -ltr` 命令的功能和用法
|
Shell 开发工具
chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判 断当前用户对/tmp/fiile1文件 是否不可读且不可写 ?
chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判 断当前用户对/tmp/fiile1文件 是否不可读且不可写 ?
69 1
|
Shell 开发工具 Perl
写一个脚本/root/bin/sumid.sh,计算/etc/passwd 文件中的第10个用户和第20用户的ID之和
写一个脚本/root/bin/sumid.sh,计算/etc/passwd 文件中的第10个用户和第20用户的ID之和
76 1
|
Shell 开发工具
编写脚本/root/bin/nologin.sh和login.sh,实现禁止和允许普通用户登录系统。
编写脚本/root/bin/nologin.sh和login.sh,实现禁止和允许普通用户登录系统。
124 1
|
Shell Linux
Shell /dev/null 文件的含义
Shell /dev/null 文件的含义
96 0