• 20155219--pwd指令的简单实现


    pwd指令的简单实现

    • pwd命令作用

    Linux中用** pwd **命令来查看”当前工作目录“的完整路径。 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录。
    在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的确切位置。

    1.命令格式:
    pwd [选项]

    2.命令功能:
    查看”当前工作目录“的完整路径

    3.常用参数:
    一般情况下不带任何参数
    如果目录是链接时:
    格式:pwd -P 显示出实际路径,而非使用连接(link)路径。

    首先通过man pwd查看pwd的详细用法,如下图:

    知道了函数getcwd可能对于pwd命令的实现有所帮助,之后通过命令man getcwd查看此函数的具体用法
    如下图:

    知道了可以通过此函数来简单实现pwd命令。
    可以采取令 buf 为 NULL并使 size 为零(百度百科里介绍可以使用负值但我测试的时候是段错误)来使 getcwd 调用 malloc 动态给 buf 分配,但是这种情况要特别注意使用后释放缓冲以防止内存泄漏。

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    int main(void)
    {
        char *path = NULL;
        path = getcwd(NULL,0);
        puts(path);
        free(path);
        return 0;
    }
    
    • 通过命令man -k status|grep 2查找可用函数,如下图所示

    老师在课堂给出提示使用stat函数

    • 1.stat函数讲解
    stat函数讲解
    
    表头文件:    #include <sys/stat.h>
                 #include <unistd.h>
    定义函数:    int stat(const char *file_name, struct stat *buf);
    函数说明:    通过文件名filename获取文件信息,并保存在buf所指的结构体stat中
    返回值:      执行成功则返回0,失败返回-1,错误代码存于errno
    
    • 2 文件对应的属性
      通过man 2 stat查看函数stat
      image
      通过上面提供的函数,返回一个结构体,保存着文件的信息。

    这一个结构体的成员表示,文件的索引信息(进入点),“number”告诉我们它是一个数字表示,而不是一个确切的路径,这就好比我们有时候用文件描述符来操作文件,而不用字符数组(文件名)来操作。
    也就是说,我们想要找到文件的路径,st_ino这个信息试关键。

    具体思路:

    计算机内核为每一个目录都设置了一个指向自己的i节点入口,即".",还有一个指向其父目录i节点的入口,即”..",我们可以使用cd . 或者cd .. 来回到当前目录下或者父目录下。我们首先获取当前目录的i节点编号,但是并不能知道当前目录的名称,我们切换到其的父目录,在里面寻找当前i节点编号对应的文件名即可。这样我们就很容易联想到使用递归来实现,但是终止条件是什么呢?在Unix文件系统的根目录中,“."和“..”指向同一个i节点,我们可以以此判断是否发到达了根目录。如下图所示:

    伪代码如下:

    while(“."和“..”不指向同一个i节点)
    切换到当前的父目录,在里面寻找当前i节点编号对应的文件名
    收集
    
    最后打印字符数组
    
    • get_inode函数--使用stat函数来得到当前目录下的文件信息,主要是获得i-node信息。
    ino_t get_inode(char *dirname)  
    {  
        struct stat a;  
        if (stat(dirname, &info) == -1)  
        {  
            perror("dirname");  
            exit(1);  
        }  
      
        return a.st_ino;  
    }  
    
    • 要读取路径,必定要先打开路径,路径如何打开可以用指令查询一下:man -k dir | grep open 得到函数opendir
      如下图

    输入指令:man 3 opendir查看详细信息

    输入参数为一个文件(目录)名,才能打开该目录,并且返回为DIR类型

    我们已经知道目录名,当前目录的目录名为.,父级目录的目录名为..。

    • 如何将它的各个父目录读取出来呢?跟读取有关(read)
      用指令搜索查询一下:man -k dir | grep read
      如下图:

    找到相关项后输入指令:man readdir

    其中有d_ino和d_name[256],这两者应该是一一对应的,也就是说我只要取得了其索引号,就可以将其翻译为文件名了。

    使用函数void inode_to_dirname(ino_t inode_num, char buf,int buflen) 来获得当前文件名,并添加到buf中

    void inode_to_dirname(ino_t inode_num, char *buf,int buflen)  
    {  
        DIR *dir_ptr;  
        struct dirent *dire;  
        if ((dir_ptr = opendir(".")) == NULL)  
        {  
            perror(".");  
            exit(1);  
        }  
      
        while ((dire = readdir(dir_ptr)) != NULL)  
        {  
            if (dire->d_ino == inode_num)  
            {  
                strncpy(buf, dire->d_name, buflen);  
                buf[strlen(buf)] = '';  
                closedir(dir_ptr);  
                return ;  
            }  
        }  
        fprintf(stderr, "error looking for inode number %d
    ", (int)inode_num);  
        exit(1);  
    }  
    

    此函数是将索引节点转化为相应的文件名的过程,具体方法是将一个个读取的目录的ino信息与传参进来的ino信息做比对,如果相同,则说明找到了正确目录,把文件名拷贝到字符数组就行;如果比对结果不相同,则继续读取下一个目录。

    void get_work_dir(ino_t inode_num)  
    {  
        ino_t parent_inode;  
        char buf[SIZE];  
        if (get_inode("..") != inode_num)  
        {  
            chdir("..");  
            inode_to_dirname(inode_num, buf, SIZE);  
            parent_inode = get_inode(".");  
            get_work_dir(parent_inode);  
            printf("/%s", buf);  
        }  
    }  
    

    此函数实现了递归调用,具体实现内容如下:

    传入一个索引节点,并求得父目录的索引节点,判断两者是否相等,相等则说明已经到了根文件夹下,可以终止递归调用
    如若不相等,则进入父目录,然后通过inum_to_name函数功能,将之前的目录名拷贝到its_name字符数组中,准备输出打印

    具体代码

    实现效果如下图

  • 相关阅读:
    AngularJS学习之旅
    webbug3.0菜鸟笔记1
    CTF练习(1)这是一张单纯的图片?
    三步删除U深度,老毛桃,大白菜捆绑软件!!
    flex弹性布局学习总结
    C# 播放音乐
    获取文件夹中的所有文件名
    C# 利用委托和事件 传入一个参数进行进行计算并返回结果
    C# 自定义颜色
    检测键盘是否按下指定按键
  • 原文地址:https://www.cnblogs.com/paypay/p/7860361.html
Copyright © 2020-2023  润新知