从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编程实践教程》
目录
相关文章
|
9月前
|
Shell 开发工具
写一个脚本/root/bin/sumspace.sh,传递两个文件 路径作为参数给脚本,计算这两个文件中所有空白行之和
写一个脚本/root/bin/sumspace.sh,传递两个文件 路径作为参数给脚本,计算这两个文件中所有空白行之和
53 1
|
9月前
pwd踩坑记之pwd 软连接如何显示物理位置
今天使用pwd获取脚本的目录,脚本一直执行失败。后来发现所在目录为软连接,而脚本是在软连接指向的物理位置,软连接的内容没有更新。
59 0
|
6月前
|
Linux
详细介绍 `ls -ltr` 命令的功能和用法
详细介绍 `ls -ltr` 命令的功能和用法
130 1
详细介绍 `ls -ltr` 命令的功能和用法
|
9月前
|
Shell 开发工具
chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判 断当前用户对/tmp/fiile1文件 是否不可读且不可写 ?
chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判 断当前用户对/tmp/fiile1文件 是否不可读且不可写 ?
43 1
|
9月前
|
Shell 开发工具 Perl
写一个脚本/root/bin/sumid.sh,计算/etc/passwd 文件中的第10个用户和第20用户的ID之和
写一个脚本/root/bin/sumid.sh,计算/etc/passwd 文件中的第10个用户和第20用户的ID之和
53 1
|
Linux
Linux目录和文件管理:pwd、cd、ls、alias、du(中)
目录和文件管理 由于 Linux 系统免费开源,使得 Linux 发行版本有很多,利用 Linux 开发产品的团队也有很多,如果任由每个人都按照自己的想法来配置 Linux 系统文件目录,后期可能会产生诸多的管理问题。试想,如果你进入一家公司,所用 Linux 系统的文件目录结构与所学的完全不同,实在令人头疼。 为了避免诸多使用者对 Linux 系统目录结构天马行空,Linux 基金会发布了 FHS 标准。多数 Linux 发行版系统都遵循这一标准。
233 0
|
Linux
Linux目录和文件管理:pwd、cd、ls、alias、du(下)
目录和文件管理 由于 Linux 系统免费开源,使得 Linux 发行版本有很多,利用 Linux 开发产品的团队也有很多,如果任由每个人都按照自己的想法来配置 Linux 系统文件目录,后期可能会产生诸多的管理问题。试想,如果你进入一家公司,所用 Linux 系统的文件目录结构与所学的完全不同,实在令人头疼。 为了避免诸多使用者对 Linux 系统目录结构天马行空,Linux 基金会发布了 FHS 标准。多数 Linux 发行版系统都遵循这一标准。
128 0
|
存储 缓存 关系型数据库
Linux目录和文件管理:pwd、cd、ls、alias、du(上)
目录和文件管理 由于 Linux 系统免费开源,使得 Linux 发行版本有很多,利用 Linux 开发产品的团队也有很多,如果任由每个人都按照自己的想法来配置 Linux 系统文件目录,后期可能会产生诸多的管理问题。试想,如果你进入一家公司,所用 Linux 系统的文件目录结构与所学的完全不同,实在令人头疼。 为了避免诸多使用者对 Linux 系统目录结构天马行空,Linux 基金会发布了 FHS 标准。多数 Linux 发行版系统都遵循这一标准。
185 0
CentOS cp 复制隐藏文件提示 cp: cannot stat ?.xxx*?. No such file or directory
执行的命令与错误信息: # cp -a /etc/skel/* /home/postgrescp: cannot stat ?.etc/skel/*?. No such file or directory 使用cp复制普通文件时,可以使用 * 号通配符,而在复制隐藏文件时,需要使用.
4269 0