Linux学习日记13——目录操作

学习视频链接

黑马程序员-Linux系统编程_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1KE411q7ee?p=65&spm_id_from=pageDriver

目录

一、getcwd 和 chdir 函数

1.1 getcwd函数

1.2 chdir 函数

1.3 测试案例

二、文件和目录权限

2.1 vim查看目录

2.2 目录权限和文件权限区别

三、opendir、readdir、closedir函数

3.1 opendir 函数

3.2 readdir

3.3 closedir 函数

3.4 测试案例

四、案例:递归遍历指定目录

4.1 Linux遍历目录命令

4.2 思路

4.3 代码

4.4 实现另外一些功能

五、重定向 dup 和 dup2 函数

5.1 Linux 自带重定向

5.2 dup 和 dup2 函数

5.3 dup2实现重定向效果

六、fcntl函数实现dup2

6.1 函数

6.2 操作


一、getcwd 和 chdir 函数

1.1 getcwd函数

1、作用

获取进程当前工作目录(卷3 标库函数:man 3 getcwd)

2、char *getcwd(char *buf, size_ t size);

成功 buf 中保存当前进程工作目录位置

失败返回 NULL

1.2 chdir 函数

1、作用

改变当前进程的工作目录。

2、int chdir(const char *path); 

成功 返回 0 

失败 返回 -1,设置 errno 为相应的值

1.3 测试案例

获取及修改当前进程的工作目录,并打印至屏幕

Linux学习日记13——目录操作_第1张图片

 Linux学习日记13——目录操作_第2张图片

二、文件和目录权限

2.1 vim查看目录

1、目录内容:

目录文件也是 “文件”。其文件内容是该目录下所有子文件的目录项 dentry。可以尝试用 vim 打开一个目录。

2、用 vim 打开目录

Linux学习日记13——目录操作_第3张图片

Linux学习日记13——目录操作_第4张图片

 下面 imp_cd.c 和 a 是目录项

2.2 目录权限和文件权限区别

r w x
文件 文件的内容可以被查看
cat、more、less...
内容可以被修改
vi、>、...
可以运行产生一个进程
./文件名
目录 目录可以被浏览
ls、tree...
创建、删除、修改文件
mv、touch、mkdir...

可以被打开、进入
cd

修改文件夹权限

Linux学习日记13——目录操作_第5张图片

三、opendir、readdir、closedir函数

3.1 opendir 函数

1、作用

根据传入的目录名打开一个目录(库函数,不是系统调用,查看这个函数在第三卷 man 3 opendir)

2、DIR *opendir(const char *name);

成功返回指向该目录结构体指针,失败返回 NULL

参数支持相对路径、绝对路径两种方式:例如:打开当前目录:① getcwd(),opendir()    ② opendir(".");

3.2 readdir

1、作用

读取目录(库函数)

2、struct dirent *readdir(DIR *dirp);

成功返回目录项结构体指针

失败返回 NULL,设置 errno 为相应值

需注意返回值,读取数据结束时也返回 NULL 值,所以应借助 errno 进一步加以区分

3、struct 结构体 

Linux学习日记13——目录操作_第6张图片

其成员变量重点记忆两个:d_ino、 d_name。实际应用中只使用到 d_name

因为 d_name 数组最大为 256,所以目录项限定为 255(名字 + \n 要小于 256)

3.3 closedir 函数

1、作用

关闭打开的目录。

2、int closedir(DIR *dirp);

成功返回 0

失败返回 -1,设置 errno 为相应值

3.4 测试案例

1、使用上述三个函数实现一个 ls 的效果

2、C语言代码

Linux学习日记13——目录操作_第7张图片

3、编译执行

Linux学习日记13——目录操作_第8张图片

4、不显示 .. 和 .

Linux学习日记13——目录操作_第9张图片

 Linux学习日记13——目录操作_第10张图片

四、案例:递归遍历指定目录

4.1 Linux遍历目录命令

Linux学习日记13——目录操作_第11张图片

4.2 思路

Linux学习日记13——目录操作_第12张图片

4.3 代码

1、简易版本

#include 
#include 
#include 
#include 
#include 
#include 

void isFile(char *name)
{
    int ret = 0;
    struct stat sb; 
    
    ret = stat(name, &sb);
    if (ret == -1) {
        perror("stat error");
        return;
    }   

    if (S_ISDIR(sb.st_mode)) {  // 如果是文件夹,进行的操作
    
    }   
    printf("%s\t%ld\n", name, sb.st_size);

    return;
}


int main(int argc, char *argv[])
{
    if (argc == 1) {  // 没有传入文件的时候 ./ls-R,默认传入 ./ls-R 。
        isFile(".");
    }   
    else {
        isFile(argv[1]);
    }   

    return 0;
}

Linux学习日记13——目录操作_第13张图片

2、完善

#include 
#include 
#include 
#include 
#include 
#include 
#include 

void isFile(char *name);
void read_dir(char *dir);

// 打开、读取目录,处理目录
void read_dir(char *dir)
{
    char path[256];  // 存储拼接后的文件绝对路径
    DIR *dp;
    struct dirent *sdp;

    dp = opendir(dir);
    if (dp == NULL) {
        perror("opendir error");
        return;
    }   

    // 读取目录项
    while ((sdp = readdir(dp)) != NULL) {
        if (strcmp(sdp->d_name, ".") == 0 || strcmp(sdp->d_name, "..") == 0) {
            continue;
        }
        // 目录项本身不可访问,需要拼接 目录/目录项   
        sprintf(path, "%s/%s", dir, sdp->d_name);
        
        // 判断文件类型,目录递归进入,文件显示名字/大小
        isFile(path);
    }   

    closedir(dp);

    return;
}

void isFile(char *name)
{
    int ret = 0;
    struct stat sb;

    // 获取文件属性,判断文件类型
    ret = stat(name, &sb);
    if (ret == -1) {
        perror("stat error");
        return;
    }

    // 如果是目录文件就进行下面的操作
    if (S_ISDIR(sb.st_mode)) {
        read_dir(name);
    }

    // 是普通文件,显示名字/大小
    printf("%10s\t%ld\n", name, sb.st_size);

    return;
}


int main(int argc, char *argv[])
{
    // 判断命令行参数
    if (argc == 1) {  // 没有传入文件的时候 ./ls-R,默认传入 ./ls-R 。
        isFile(".");
    }
    else {
        isFile(argv[1]);
    }

    return 0;
}

 Linux学习日记13——目录操作_第14张图片

3、优化

(1) 根据警告中的内容,可以做一个长度判断

如果拼接长度大于 256 要做一个错误处理

(2) 修改为主调和回调函数(涉及到函数指针)

4.4 实现另外一些功能

统计目录及其子目录中普通文件的个数

五、重定向 dup 和 dup2 函数

5.1 Linux 自带重定向

重定向 > :cat 文件名 > 文件名

可以把本来准备写到屏幕上的东西,现在写到文件里面去

5.2 dup 和 dup2 函数

1、函数原型

int dup(int oldfd);

int dup2(int oldfd, int newfd);

当调用 dup 和 dup2 函数时,内核在进程中创建一个新的文件描述符,此描述符是当前可用文件描述符的最小数值,这个文件描述符指向 oldfd 所拥有的文件表项。这个文件描述符作为函数的返回值被返回出来。

若有错误则返回 -1,errno 会存放错误代码

2、简单使用

Linux学习日记13——目录操作_第15张图片

 Linux学习日记13——目录操作_第16张图片

Linux学习日记13——目录操作_第17张图片

5.3 dup2实现重定向效果

1、实现原理

int dup2(int oldfd, int newfd);

dup2 函数的妙用就是让 newfd 文件描述符指向 oldfd

现在我们可以让指向屏幕上的东西不再指向屏幕,而是指向文件。

在屏幕上打印,等同于写入文件 

Linux学习日记13——目录操作_第18张图片

2、代码

Linux学习日记13——目录操作_第19张图片

3、编译运行,查看结果

Linux学习日记13——目录操作_第20张图片

Linux学习日记13——目录操作_第21张图片

六、fcntl函数实现dup2

6.1 函数

int fcntl(int fd, int cmd, ...)

cmd 传入相应的宏:F_DUPFD

参数3:文件描述符被其他文件占用时,返回最小可用的文件描述符。未被占用就返回 >= 该值的文件描述符

6.2 操作

Linux学习日记13——目录操作_第22张图片

 Linux学习日记13——目录操作_第23张图片

因为文件描述符 0 1 2 3 都被占了,所以 newfd 返回 4,文件描述符 7 没有被占,所以 newfd2 返回 7

最终我们使用 newfd2 指向 fd1 文件描述符指向对象,并且使用 newfd2 进行了写操作

Linux学习日记13——目录操作_第24张图片

 

你可能感兴趣的:(linux,linux)