remove 是 C 标准库(C89/C90 及之后)中用于删除文件或目录的函数,它是一个更高级、更通用的接口,封装了底层的 unlink 和 rmdir 系统调用。

(图片来源网络,侵删)
函数原型
remove 函数在 <stdio.h> 头文件中声明。
#include <stdio.h> int remove(const char *pathname);
功能描述
remove 函数尝试删除由 pathname 指定的文件或目录。
pathname是一个普通文件、符号链接、管道(FIFO)、套接字(socket):remove函数会调用unlink()系统调用来删除它。pathname是一个空目录:remove函数会调用rmdir()系统调用来删除它。pathname是一个非空目录:remove函数会失败,并设置errno为ENOTEMPTY(或EEXIST)。
remove 是一个“一刀切”的删除函数,它会根据路径的类型自动选择正确的删除方式。
参数
pathname: 一个指向以 null 结尾的字符串的指针,表示要被删除的文件或目录的路径,可以是相对路径或绝对路径。
返回值
- 成功:返回
0。 - 失败:返回
-1,并且会设置errno来指示具体的错误原因。
错误码 (errno)
当 remove 失败时,可以通过检查 errno 的值来定位问题,常见的错误码包括:

(图片来源网络,侵删)
| 错误码 | 宏定义 (在 <errno.h> 中) |
描述 |
|---|---|---|
EACCES |
EACCES |
没有足够的权限来删除文件或目录(没有写权限,或者不是目录的所有者)。 |
EBUSY |
EBUSY |
无法删除,因为文件正在被使用(一个进程正在打开该文件)。 |
EEXIST |
EEXIST |
要删除的目录非空,这是最常见的错误之一。 |
EFAULT |
EFAULT |
pathname 指针指向了无效的内存地址。 |
EINVAL |
EINVAL |
参数无效(尝试删除 或 )。 |
EISDIR |
EISDIR |
pathname 是一个目录,但该目录非空,这与 EEXIST 经常是同一个错误。 |
ELOOP |
ELOOP |
解析 pathname 时遇到了太多的符号链接。 |
ENOENT |
ENOENT |
pathname 指定的文件或目录不存在。 |
ENOMEM |
ENOMEM |
内存不足。 |
ENOTDIR |
ENOTDIR |
pathname 中有一个路径分量不是一个目录。 |
EROFS |
EROFS |
位于一个只读文件系统上。 |
EPERM |
EPERM |
操作被禁止(尝试删除一个设置了 sticky bit 的目录中的文件,且你不是文件所有者)。 |
使用示例
示例 1:删除一个普通文件
#include <stdio.h>
#include <stdlib.h> // 用于 exit()
int main() {
const char *filename = "test.txt";
// 首先创建一个文件用于测试
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
perror("fopen failed");
return 1;
}
fprintf(fp, "Hello, world!");
fclose(fp);
printf("File '%s' created.\n", filename);
// 删除文件
if (remove(filename) == 0) {
printf("File '%s' deleted successfully.\n", filename);
} else {
// 使用 perror 打印带有错误信息的描述
perror("remove failed");
}
return 0;
}
编译与运行:
gcc -o remove_example remove_example.c ./remove_example
预期输出:
File 'test.txt' created.
File 'test.txt' deleted successfully.
示例 2:删除一个空目录
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h> // 用于 mkdir
int main() {
const char *dir_path = "my_empty_dir";
// 创建一个空目录用于测试
if (mkdir(dir_path, 0777) == -1) {
perror("mkdir failed");
return 1;
}
printf("Directory '%s' created.\n", dir_path);
// 删除空目录
if (remove(dir_path) == 0) {
printf("Directory '%s' deleted successfully.\n", dir_path);
} else {
perror("remove failed");
}
return 0;
}
示例 3:尝试删除一个非空目录(会失败)
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main() {
const char *dir_path = "my_non_empty_dir";
const char *file_in_dir = "my_non_empty_dir/another_file.txt";
// 创建目录
if (mkdir(dir_path, 0777) == -1) {
perror("mkdir failed");
return 1;
}
printf("Directory '%s' created.\n", dir_path);
// 在目录中创建一个文件
FILE *fp = fopen(file_in_dir, "w");
if (fp == NULL) {
perror("fopen failed");
return 1;
}
fprintf(fp, "This file prevents directory deletion.");
fclose(fp);
printf("File created inside directory.\n");
// 尝试删除非空目录
if (remove(dir_path) == 0) {
printf("Directory '%s' deleted successfully.\n", dir_path);
} else {
perror("remove failed"); // 这里会打印错误信息
// 错误原因通常是 "Directory not empty" 或 "File exists"
}
return 0;
}
预期输出:
Directory 'my_non_empty_dir' created.
File created inside directory.
remove failed: Directory not empty
remove 与 unlink 的区别
这是在 Linux C 编程中一个非常重要的知识点。

(图片来源网络,侵删)
| 特性 | remove |
unlink |
|---|---|---|
| 头文件 | <stdio.h> |
<unistd.h> |
| 功能 | 删除文件或空目录 | 仅删除文件(包括符号链接) |
| 目录操作 | 可以删除空目录 | 不能删除目录 |
| 底层实现 | remove 是一个库函数,内部根据情况调用 unlink 或 rmdir。 |
unlink 是一个系统调用(System Call)。 |
| 主要用途 | 通用删除,当你不确定对象类型时,或者想删除一个空目录。 | 精确地删除一个文件链接,常用于文件操作,不关心目录。 |
简单总结:
- 如果你想删除一个文件,用
remove和unlink都可以,但unlink更底层、更直接。 - 如果你想删除一个空目录,必须用
remove(或rmdir),unlink对目录无效。 - 如果你想删除一个非空目录,
remove和unlink都会失败,你需要先递归删除目录下的所有内容,然后再删除该目录(通常使用rmdir)。
最佳实践
- 检查返回值:始终检查
remove的返回值,以确保操作成功。 - 使用
perror:当remove失败时,使用perrror函数可以快速定位问题,因为它会打印出系统错误信息。 - 处理非空目录:如果要删除一个目录及其所有内容,你需要自己实现递归删除逻辑,或者使用
system("rm -rf /path/to/dir")(不推荐,有安全风险)。 - 注意权限:确保你的程序有权限删除目标文件或目录,在多用户系统中,这是一个常见的问题。
