创建,删除,打开,关闭目录,以及获取当前目录,目录跳转(十)

目录

一 新建目录——mkdir() 函数

1.1 mkdir函数原型:

1.2mkdir()代码测试

二 删除目录——rmdir() 函数

2.1 rmdir 函数函数原型:

2.2rmdir 函数测试

三 打开、读取以及关闭目录

3.1 opendir()函数原型:

3.2读取目录 readdir()函数原型:

3.3 struct dirent 结构体:

3.4rewinddir ()函数

3.5 关闭目录 closedir ()函数

四 案例练习

练习1

五 获取进程的当前工作目录

5.1 getcwd() 函数

5.2代码测试——获取当前路径

​编辑

六改变当前工作目录chdir()和 fchdir()

6.1 chdir()和 fchdir()函数原型:

6.2 代码测试

 七 remove 函数删除文件

7.1函数原型:

7.2代码测试:


目录块当中有多个目录项(或叫目录条目),每一个目录项(或目录条目)都会对应到该目录下的某一 个文件,目录项当中记录了该文件的文件名以及它的 inode 节点编号,所以通过目录的目录块便可以遍历找 到该目录下的所有文件以及所对应的 inode 节点。

所以对此总结如下:

  •  普通文件由 inode 节点和数据块构成
  •  目录由 inode 节点和目录块构成

一 新建目录——mkdir() 函数

1.1 mkdir函数原型:

#include <sys/stat.h> 
#include <sys/types.h> 
 
int mkdir(const char *pathname, mode_t mode); 

函数参数和返回值含义如下:

  • pathname:需要创建的目录路径。
  • mode:新建目录的权限设置,设置方式与 open 函数的 mode 参数一样,最终权限为(mode & ~umask)。与清0,或置1
  • 返回值:成功返回 0;失败将返回-1,并会设置 errno。

pathname 参数指定的新建目录的路径,该路径名可以是相对路径,也可以是绝对路径,若指定的路径 名已经存在,则调用 mkdir()将会失败。 mode 参数指定了新目录的权限,目录拥有与普通文件相同的权限位,但是其表示的含义与普通文件却 有不同

1.2mkdir()代码测试

#include "stdio.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>

int main()
{
    int ret = mkdir("./next",0777);
    if(-1 == ret)
    {
            perror("mkdir error :");
            exit(-1);
    }
    return 0;
}

 当执行完./a.out时在当前目录下生成一个next目录文件

 

二 删除目录——rmdir() 函数

2.1 rmdir 函数函数原型:

#include <unistd.h> 
 
int rmdir(const char *pathname); 

首先,使用该函数需要包含头文件。

函数参数和返回值含义如下:

  • pathname:需要删除的目录对应的路径名,并且该目录必须是一个空目录,也就是该目录下只有.和..这 两个目录项;pathname 指定的路径名不能是软链接文件,即使该链接文件指向了一个空目录。
  • 返回值:成功返回 0;失败将返回-1,并会设置 errno。

2.2rmdir 函数测试

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define   MY_FILE "./next"

void main()
{
    int ret = rmdir(MY_FILE);
    if(-1 == ret)
    {
        perror("");
        exit(-1);
    }
}

代码执行完后,刚才创建的next文件被删除

三 打开、读取以及关闭目录

打开、读取、关闭一个普通文件可以使用 open()、read()、close(),而对于目录来说,可以使用 opendir()、readdir()和 closedir()来打开、读取以及关闭目录。

3.1 opendir()函数原型:

opendir()函数用于打开一个目录,并返回指向该目录的句柄,供后续操作使用。Opendir 是一个 C 库函数。

opendir()函数原型:

#include <sys/types.h> 
#include <dirent.h> 
 
DIR *opendir(const char *name); 

函数参数和返回值含义如下:

  • name:指定需要打开的目录路径名,可以是绝对路径,也可以是相对路径。
  • 返回值:成功将返回指向该目录的句柄,一个 DIR 指针(其实质是一个结构体指针),其作用类似于open函数返回的文件描述符fd,后续对该目录的操作需要使用该DIR指针变量;若调用失败,则返回NULL。

3.2读取目录 readdir()函数原型:

readdir()用于读取目录,获取目录下所有文件的名称以及对应 inode 号。 readdir()是 一个 C 库函数(事实上 Linux 系统还提供了一个 readdir 系统调用),其函数原型如下所示:

#include <dirent.h> 
 
struct dirent *readdir(DIR *dirp); 

函数参数和返回值含义如下:

  • dirp:目录句柄 DIR 指针。
  • 返回值:返回一个指向 struct dirent 结构体的指针,该结构体表示 dirp 指向的目录流中的下一个目录条 目。在到达目录流的末尾或发生错误时,它返回 NULL。

Tips:“流”是从自然界中抽象出来的一种概念,有点类似于自然界当中的水流,在文件操作中,文件 内容数据类似池塘中存储的水,N 个字节数据被读取出来或将 N 个字节数据写入到文件中,这些数据就构 成了字节流。 “流”这个概念是动态的,而不是静态的。编程当中提到这个概念,一般都是与 I/O 相关,所以也经 常叫做 I/O 流;但对于目录这种特殊文件来说,这里将目录块中存储的数据称为目录流,存储了一个一个 的目录项(目录条目)。

3.3 struct dirent 结构体:

struct dirent { 
 ino_t d_ino; /* inode 编号 */ 
 off_t d_off; /* not an offset; see NOTES */ 
 unsigned short d_reclen; /* length of this record */ 
 unsigned char d_type; /* type of file; not supported by all filesystem types */ 
 char d_name[256]; /* 文件名 */ 

}; 

对于 struct dirent 结构体,我们只需要关注 d_ino 和 d_name 两个字段即可,分别记录了文件的 inode 编 号和文件名,其余字段并不是所有系统都支持,所以也不再给大家介绍,这些字段一般也不会使用到。

每调用一次 readdir(),就会从 drip 所指向的目录流中读取下一条目录项(目录条目),并返回 struct dirent结构体指针,指向经静态分配而得的 struct dirent 类型结构,每次调用 readdir()都会覆盖该结构。一旦遇到 目录结尾或是出错,readdir()将返回 NULL,针对后一种情况,还会设置 errno 以示具体错误。那如何区别究 竟是到了目录末尾还是出错了呢,可通过如下代码进行判断:

#include <errno.h> 
 error = 0; 
 
 direntp = readdir(dirp); 
 if (NULL == direntp) { 
 if (0 != error) { 
 /* 出现了错误 */ 
 } else { 
 /* 已经到了目录末尾 */ 
 } 
 } 

 这段代码很好理解,观察上面一段伪代码,error变量来自于errno头文件,将error变量设置为0,readdir()返回空指针时证明函数执行出错,那究竟是目录末尾还是出错了呢,如果0!=error的话,那就证明erro值被内核设置了,证明出错了

3.4rewinddir ()函数

rewinddir()是 C 库函数,可将目录流重置为目录起点,以便对 readdir()的下一次调用将从目录列表中的 第一个文件开始。rewinddir 函数原型如下所示:

#include <sys/types.h> 
#include <dirent.h> 
 
void rewinddir(DIR *dirp); 

函数参数和返回值含义如下:

  • dirp:目录句柄。
  • 返回值:无返回值。

3.5 关闭目录 closedir ()函数

closedir()函数用于关闭处于打开状态的目录,同时释放它所使用的资源,其函数原型如下所示:

函数参数和返回值含义如下:

#include <sys/types.h> 
#include <dirent.h> 
 
int closedir(DIR *dirp);
  • dirp:目录句柄。
  • 返回值:成功返回 0;失败将返回-1,并设置 errno。

四 案例练习

练习1

1. 打开一个目录、并将目录下的所有文件的名称 以及其对应 inode 编号打印出来。

示例代码如下所示:

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



#define   MY_FILE "./next"

void main()
{
    //1创建目录
    /*
    int ret = mkdir(MY_FILE,0777);
    if(-1 == ret)
    {
        perror("");
        exit(-1);
    }
*/
    //2打开目录文件
    DIR *fdir;
    fdir = opendir(MY_FILE);
    if(NULL == fdir)
    {
        perror("opendir");
    }
    int fd1 = open("./next/test.c", O_RDWR|O_CREAT, 0777);
    if(-1 == fd1)
    {
        perror("");
    }


    //3目录文件里面的文件以及inode编号
    errno = 0;
    struct dirent *ret1 ; 
    while(NULL != ( ret1 = readdir(fdir)))
    {
        printf("inode:%ld        name:%s \n",ret1->d_ino,ret1->d_name);
    }
    if(NULL == ret1)
    {
        if (errno != 0)
        {
            puts("读取目录文件出错\n");
        }else
        {
            puts("readdir succeed\n");
        }
    }

    //4关闭目录文件
    closedir(fdir);

}

由此可知,示例代码 能够将next目录下的所有文件全部扫描出来,打印出它们的名字以及 inode节点。

五 获取进程的当前工作目录

Linux 下的每一个进程都有自己的当前工作目录(current working directory),当前工作目录是该进程解析、搜索相对路径名的起点(不是以" / "斜杆开头的绝对路径)。譬如,代码中调用 open 函数打开文件时, 传入的文件路径使用相对路径方式进行表示,那么该进程解析这个相对路径名时、会以进程的当前工作目录作为参考目录。

一般情况下,运行一个进程时、其父进程的当前工作目录将被该进程所继承,成为该进程的当前工作目 录。

5.1 getcwd() 函数

来获取进程的当前工作目录

如下所示:

#include <unistd.h> 
 
char *getcwd(char *buf, size_t size);

函数参数和返回值含义如下:

  • buf:getcwd()将内含当前工作目录绝对路径的字符串存放在 buf 缓冲区中。
  • size:缓冲区的大小,分配的缓冲区大小必须要大于字符串长度,否则调用将会失败。
  • 返回值:如果调用成功将返回指向 buf 的指针,失败将返回 NULL,并设置 errno。

Tips:若传入的 buf 为 NULL,且 size 为 0,则 getcwd()内部会按需分配一个缓冲区,并将指向该缓冲区 的指针作为函数的返回值,为了避免内存泄漏,调用者使用完之后必须调用 free()来释放这一缓冲区所占内 存空间。

5.2代码测试——获取当前路径

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void main()
{
    char *str = getcwd(NULL,0);
    printf("%s ",str);
    free(str);
}

六改变当前工作目录chdir()和 fchdir()

系统调用 chdir()和 fchdir()可以用于更改进程的当前工作目录

6.1 chdir()和 fchdir()函数原型:

#include <unistd.h> 
 
int chdir(const char *path); 
int fchdir(int fd); 

函数参数和返回值含义如下:

  • path:将进程的当前工作目录更改为 path 参数指定的目录,可以是绝对路径、也可以是相对路径,指定的目录必须要存在,否则会报错。
  • fd:将进程的当前工作目录更改为 fd 文件描述符所指定的目录(譬如使用 open 函数打开一个目录)。
  • 返回值:成功均返回 0;失败均返回-1,并设置 errno。

此两函数的区别在于,指定目录的方式不同,chdir()是以路径的方式进行指定,而 fchdir()则是通过文件 描述符,文件描述符可调用 open()打开相应的目录时获得。

6.2 代码测试

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void main()
{
    char *str = NULL ;

    str = getcwd(NULL,0);
    printf("%s\n ",str);
    free(str);

    /* 更改进程的当前工作目录 */ 
    int ret = chdir("/home/chen/"); 
    if (-1 == ret) { 
    perror("chdir error"); 
    exit(-1); 
    } 
    
    str = getcwd(NULL,0);
    printf("%s\n ",str);
    free(str);
}

 七 remove 函数删除文件

remove()是一个 C 库函数,用于移除一个文件或空目录,其函数原型如下所示:

7.1函数原型:

#include <stdio.h> 
 
int remove(const char *pathname); 

使用该函数需要包含 C 库函数头文件。

函数参数和返回值含义如下:

  • pathname:需要删除的文件或目录路径,可以是相对路径、也可是决定路径。
  • 返回值:成功返回 0;失败将返回-1,并设置 errno。 pathname 参数指定的是一个非目录文件,那么 remove()去调用 unlink(),如果 pathname 参数指定的是 一个目录,那么 remove()去调用 rmdir()。

与 unlink()、rmdir()一样,remove()不对软链接进行解引用操作,若 pathname 参数指定的是一个软链接 文件,则 remove()会删除链接文件本身、而非所指向的文件

7.2代码测试:

#include <stdio.h>
#include <stdlib.h>

void main()
{
    int ret = remove("./hh");
    if(-1 == ret)
    {
        perror("");
        exit(-1);
    }
}

 执行完a.out,新建的hh文件被删除

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@ChenPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值