目录
1 文件目录
1.1 文件目录简介
1.2 目录存储形式
2 创建和删除目录
2.1 mkdir创建目录
2.2 rmdir删除空目录
3 opendir打开、 readdir读取以及closedir关闭目录
3.1 打开文件 opendir
3.2 读取目录 readdir
3.3 重置目录起点rewinddir
3.4 关闭目录 closedir
3.4 示例程序
4 进程的当前工作目录
4.1 获取进程的当前工作目录getcwd
4.2 改变当前工作目录chdir()和 fchdir()
5 删除文件
5.1 unlink 函数删除文件
5.2 remove 函数删除文件
5 文件重命名renme
1 文件目录
1.1 文件目录简介
在Linux系统中,文件目录(也常称为文件夹)是一种特殊的文件,它用于组织和管理文件系统中的文件和子目录。目录本身也被视为文件,但是它们具有一些特殊的属性和操作方式,不同于普通文件。
在 Linux 系统下,会有一些专门的系统调用或 C 库函数用于对文件夹进行操作,譬如:打开、创建文件夹、删除文件夹、读取文件夹以及遍历文件夹中的文件等。
1.2 目录存储形式
目录在文件系统中的存储方式与常规文件类似,常规文件包括了 inode 节点以及文件内容数据存储块(block);但对于目录来说, 其存储形式则是由 inode 节点和目录块所构成,目录块当中记录了有哪些文件组织在这个目录下,记录它们的文件名以及对应的 inode 编号。其存储形式如下图所示:
目录块当中有多个目录项(或叫目录条目) ,每一个目录项(或目录条目) 都会对应到该目录下的某一个文件,目录项当中记录了该文件的文件名以及它的 inode 节点编号,所以通过目录的目录块便可以遍历找到该目录下的所有文件以及所对应的 inode 节点。
2 创建和删除目录
2.1 mkdir
创建目录
mkdir
函数是C语言标准库中的一个函数,用于在文件系统中创建一个新的目录。这个函数的原型如下:
#include <sys/stat.h>
int mkdir(const char *pathname, mode_t mode);
pathname
:指向一个以null结尾的字符串,指定要创建的目录的路径。mode
:用于设置新目录的权限。这个值通常使用S_IRWXU
(所有者读、写、执行权限) |S_IRWXG
(组读、写、执行权限) |S_IRWXO
(其他用户读、写、执行权限)的组合来定义。
下面是一个使用命令行参数来创建目录的示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
// 检查是否提供了目录名作为命令行参数
if (argc != 2) {
fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
return EXIT_FAILURE;
}
const char *dir = argv[1]; // 命令行参数作为目录名
mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; // 所有者、组和其他用户都有读、写、执行权限
if (mkdir(dir, mode) == -1) {
if (errno == EEXIST) {
printf("Directory '%s' already exists.\n", dir);
} else {
perror("mkdir failed"); // perror函数会打印错误信息
}
return errno;
}
printf("Directory '%s' created successfully\n", dir);
return 0;
}
程序在运行时提供一个参数,即目录名。如果用户提供了正确的参数数量,程序将尝试创建一个具有指定权限的目录。如果目录创建成功,程序将打印一条成功消息。如果目录已经存在,程序将打印一条相应的消息。如果发生其他错误,perror
函数将打印错误信息。程序运行结果如下:
2.2 rmdir
删除空目录
rmdir
函数是C语言标准库中用于删除空目录的函数。如果目录不为空,rmdir
函数将失败。以下是 rmdir
函数的原型:
#include <unistd.h>
int rmdir(const char *pathname);
pathname
:指向一个以null结尾的字符串,指定要删除的目录的路径。
下面是一个使用 main
函数和命令行参数来删除目录的示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
// 检查是否提供了目录名作为命令行参数
if (argc != 2) {
fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
return EXIT_FAILURE;
}
const char *dir = argv[1]; // 命令行参数作为目录名
if (rmdir(dir) == -1) {
if (errno == ENOTEMPTY) {
printf("Directory '%s' is not empty.\n", dir);
} else {
perror("rmdir failed"); // perror函数会打印错误信息
}
return errno;
}
printf("Directory '%s' removed successfully\n", dir);
return 0;
}
程序在运行时提供一个参数,即要删除的目录名。如果提供了正确的参数数量,程序将尝试删除该目录。如果目录删除成功,程序将打印一条成功消息。如果目录不为空,程序将打印一条相应的消息。
3 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。
每调用一次 readdir(),就会从 drip 所指向的目录流中读取下一条目录项(目录条目),并返回 struct dirent结构体指针(struct dirent 结构体记录了文件的 inode 编号和文件名等信息)。
当使用 opendir()打开目录时,目录流将指向了目录列表的头部(0) ,使用 readdir()读取一条目录条目之后,目录流将会向后移动、指向下一个目录条目。这其实跟 open()类似, 当使用 open()打开文件的时候,文件位置偏移量默认指向了文件头部,当使用 read()或 write()进行读写时,文件偏移量会自动向后移动。
3.3 重置目录起点rewinddir
rewinddir()是 C 库函数,可将目录流重置为目录起点, 以便对 readdir()的下一次调用将从目录列表中的第一个文件开始。 rewinddir 函数原型如下所示:
#include <sys/types.h>
#include <dirent.h>
void rewinddir(DIR *dirp);
- dirp: 目录句柄
3.4 关闭目录 closedir
closedir()函数用于关闭处于打开状态的目录,同时释放它所使用的资源,其函数原型如下所示:
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
3.4 示例程序
下面的示例程序接收命令行参数作为目录名,然后列出该目录下的所有文件和目录项:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
int main(int argc, char *argv[])
{
// 检查是否提供了目录名作为命令行参数
if (argc != 2) {
fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
return EXIT_FAILURE;
}
const char *dir_name = argv[1]; // 命令行参数作为目录名
DIR *dir_ptr = NULL;
struct dirent *entry;
// 打开目录以供读取
dir_ptr = opendir(dir_name);
if (dir_ptr == NULL) {
perror("opendir failed"); // perror函数会打印错误信息
return errno;
}
// 读取目录中的所有条目
while ((entry = readdir(dir_ptr)) != NULL) {
printf("%s\n", entry->d_name); // 打印文件或目录名
}
// 关闭目录流
if (closedir(dir_ptr) == -1) {
perror("closedir failed");
return errno;
}
return 0;
}
在这个示例中,程序首先检查命令行参数的数量是否正确。如果正确,它将尝试打开指定的目录。如果目录成功打开,程序将使用 readdir
函数遍历目录中的所有条目,并打印每个条目的名称。最后,使用 closedir
函数关闭目录流。程序运行结果如下:
4 进程的当前工作目录
4.1 获取进程的当前工作目录getcwd
getcwd
函数是 POSIX 标准定义的用于获取当前工作目录的完整路径的函数。以下是 getcwd
函数的原型:
#include <unistd.h>
char *getcwd(char *buf, size_t size);
buf
:指向一个字符数组的指针,用于存储当前工作目录的路径。如果为NULL
,getcwd
将分配一个足够大的缓冲区。size
:缓冲区的大小。
下面是使用 getcwd
函数的示例程序,该程序将打印当前工作目录的路径:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(void) {
char *buffer;
size_t bufferSize = 1024;
// 尝试获取当前工作目录
buffer = getcwd(NULL, bufferSize); // 使用 NULL 让 getcwd 分配缓冲区
if (buffer == NULL) {
perror("getcwd failed"); // perror 函数会打印错误信息
return errno;
}
// 打印当前工作目录
printf("Current working directory: %s\n", buffer);
// 释放 getcwd 分配的缓冲区
free(buffer);
return 0;
}
getcwd
被用来获取当前工作目录的路径,并将结果存储在 buffer
中。如果 getcwd
成功,程序将打印当前工作目录的路径。如果失败,perror
函数将打印错误信息。最后,如果 getcwd
分配了缓冲区,程序将使用 free
函数释放它。运行结果如下:
4.2 改变当前工作目录chdir()和 fchdir()
chdir()
和 fchdir()
是两个用于更改当前工作目录的函数,两个函数的原型如下:
#include <unistd.h>
int chdir(const char *path);
path
:指向以null结尾的字符串的指针,指定要切换到的目录的路径。
#include <unistd.h>
int fchdir(int fd);
fd
:文件描述符,指向一个目录的文件描述符。
5 删除文件
5.1 unlink 函数删除文件
unlink
函数用于删除文件的函数,以下是 unlink
函数的原型:
#include <unistd.h>
int unlink(const char *pathname);
pathname
:指向以null结尾的字符串的指针,指定要删除的文件的路径。
下面是一个使用 unlink
函数删除文件的示例程序,该程序接收命令行参数作为要删除的文件名:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[]) {
// 检查是否提供了文件名作为命令行参数
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
return EXIT_FAILURE;
}
const char *filename = argv[1]; // 命令行参数作为文件名
// 尝试删除文件
if (unlink(filename) == -1) {
perror("unlink failed"); // perror 函数会打印错误信息
return errno;
}
printf("File '%s' has been successfully deleted\n", filename);
return 0;
}
程序首先检查命令行参数的数量是否正确。如果正确,它将尝试删除指定的文件。如果文件删除成功,程序将打印一条成功消息。如果删除失败,perror
函数将打印错误信息。运行结果如下,从测试结果可看到,只能删除文件,不能删除文件夹
5.2 remove 函数删除文件
remove
函数是C标准库中的一个函数,它可以删除文件或空目录。与unlink
不同,remove
可以删除空目录,但不能删除非空目录。以下是remove
函数的原型:
#include <stdio.h>
int remove(const char *filename);
filename
:指向以null结尾的字符串的指针,指定要删除的文件或目录的路径。
示例程序将5.1中的unlink变为remove
,运行结果如下,从运行结果可以看到,remove
可以删除目录。
5 文件重命名renme
rename
函数用于重命名文件或目录。以下是 rename
函数的原型:
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
oldpath
:指向以null结尾的字符串的指针,指定要重命名的文件或目录的当前名称。newpath
:指向以null结尾的字符串的指针,指定新的名称。
下面是 rename
函数重命名文件的示例程序,程序接收两个命令行参数:oldpath
和 newpath
:
程序首先检查命令行参数的数量是否正确。如果正确,它将尝试将文件或目录从 oldpath
重命名为 newpath
。如果重命名成功,程序将打印一条成功消息。如果重命名失败,perror
函数将打印错误信息。