跳到主要内容

目录检索

1. 基本概念

Linux 目录检索指在 Linux 操作系统中使用目录检索工具来查找文件和目录的过程。

Linux 的文件系统包括一个根目录(/),这个目录包含了 Linux 系统中所有的文件和目录。在根目录下,还有许多子目录,每个子目录都有自己的用途,如 “/etc” 目录用于存放系统配置文件,“/usr” 目录用于存放用户程序,“/var” 目录用于存放可变文件等。

要查找文件和目录,可以使用 Linux 中的目录检索工具,如“ls”命令。使用“ls”命令时,可以指定要查找的目录,也可以使用通配符来匹配文件名,例如 “ls /etc/*.conf” 表示查找 “/etc” 目录下所有以 “.conf” 为扩展名的文件。

除了“ls”命令,还有许多其他的目录检索工具,如 “find” 命令可以在指定的目录中查找满足特定条件的文件,“grep” 命令可以用于搜索文本文件中的关键字。总之,Linux 提供了丰富的目录检索工具,可以帮助用户快速查找到所需的文件和目录。Linux 库函数中也给我们提供了一些目录操作的 API。

2. 目录操作API

2.1 目录项结构体

在 Linux 系统中的目录项结构体:

struct dirent
{
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
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]; /* filename */
};

typedef struct
{
int dd_fd; /* file descriptor */
int dd_loc; /* offset in current buffer */
int dd_size; /* amount of data returned by getdents */
char *dd_buf; /* data buffer */
struct dirent *dd_next; /* next entry to read */
} DIR;

2.2 打开目录操作

opendir() 函数用于打开一个目录,并返回目录流,用于读取目录中的文件。函数原型为:

DIR *opendir(const char *name);

该函数接受一个参数:

  • name:指定要打开的目录的路径。

该函数返回一个指向 DIR 结构体的指针,该结构体包含有关目录的信息。如果打开目录失败,则返回 NULL

2.3 关闭目录操作

closedir() 函数用于关闭一个打开的目录流。函数原型为:

int closedir(DIR *dirp);

该函数接受一个参数:

  • dirp:指向打开的目录流的指针,由 opendir() 函数返回。

该函数返回 0 表示成功,返回非 0 值表示失败。

2.4 创建目录操作

mkdir() 函数用于在指定的路径下创建一个新目录。函数原型为:

int mkdir(const char *pathname, mode_t mode);

该函数接受两个参数:

  • pathname:指定要创建新目录的路径。
  • mode:指定新目录的权限。

该函数返回 0 表示成功,返回非 0 值表示失败。

2.5 目录项偏移操作

seekdir() 函数用于更改目录流的当前位置。函数原型为:

void seekdir(DIR *dirp, long loc);

该函数接受两个参数:

  • dirp:指向打开的目录流的指针,由 opendir() 函数返回。
  • loc:指定新的当前位置。

该函数没有返回值。

2.6 读取目录操作

readdir() 函数用于读取目录流中的下一个条目。函数原型为:

struct dirent *readdir(DIR *dirp);

该函数接受一个参数:

  • dirp:指向打开的目录流的指针,由 opendir() 函数返回。

该函数返回一个指向 dirent 结构体的指针,该结构体包含有关目录条目的信息。如果已到达目录流的末尾,则返回 NULL

2.7 目录删除操作

remove() 函数用于删除指定路径下的文件或目录。函数原型为:

int remove(const char *pathname);

该函数接受一个参数:

  • pathname:指定要删除的文件或目录的路径。

该函数返回 0 表示成功,返回非 0 值表示失败。注意,该函数只能删除空目录。如果要删除非空目录,可以使用 rmdir() 函数。

注意:这个函数也可以用来删除文件。

3. 路径操作API

3.1 改变当前工作目录

chdir() 函数用于更改当前工作目录。函数原型为:

int chdir(const char *path);

该函数接受一个参数:

  • path:指定要更改为的新工作目录的路径。

该函数返回 0 表示成功,返回非 0 值表示失败。

3.2 获取当前绝对路径

getcwd() 函数用于获取当前工作目录。函数原型为:

char *getcwd(char *buf, size_t size);

该函数接受两个参数:

  • buf:指向字符数组的指针,该字符数组用于保存当前工作目录的路径。
  • size:指定 buf 数组的大小,以便确定 buf 数组的最大长度。

该函数返回值为指向字符数组 buf 的指针,表示当前工作目录的路径。如果发生错误,则返回 NULL。

4. 示例代码

4.1 简单示例

演示打开目录、读取目录并打印wen'j、关闭目录。

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

int main(int argc, char *argv[])
{
// 打开目录
DIR *dp = opendir(".");
if (dp == NULL) {
perror("opendir() fail");
exit(1);
}

// 读取目录文件
struct dirent *d;
while ((d = readdir(dp)) != NULL) {
// 打印目录文件名
printf("%s\n", d->d_name);
}

// 关闭目录
closedir(dp);

return 0;
}

4.2 简单示例

演示创建目录、切换路径、删除目录。

下面是一个示例代码,它使用这些函数来在当前目录中创建一个名为 "temp" 的子目录,然后将当前工作目录更改为该子目录,并在其中创建一个名为 "test.txt" 的文件,然后将当前工作目录更改回原来的目录,并删除 "temp" 子目录。

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

int main(int argc, char *argv[])
{
// 创建 "temp" 子目录
int ret = mkdir("temp", 0644);
if (ret != 0) {
perror("mkdir() fail");
exit(1);
}

// 更改当前工作目录为 "temp" 子目录
ret = chdir("temp");
if (ret != 0){
perror("chdir() fail");
exit(1);
}

// 在 "temp" 子目录中创建 "test.txt" 文件
FILE *fp = fopen("test.txt", "w");
if (fp == NULL) {
perror("fopen() fail");
exit(1);
}

// 关闭 "test.txt" 文件
fclose(fp);

// 打印当前目录
char buf[256] = {0};
getcwd(buf, 256);
printf("当前目录:%s\n", buf);

// 将当前工作目录更改回原来的目录
if (chdir("..") == -1) {
perror("chdir() fail");
exit(1);
}

// 打印当前目录
getcwd(buf, 256);
printf("当前目录:%s\n", buf);

// 删除 "temp" 子目录
if (rmdir("temp") == -1) {
perror("rmdir() fail");
exit(1);
}

return 0;
}

因为 rmdir 只能删除一个非空的目录,所以上面的删除目录操作肯定是失败的。