mkdir()
mkdir 是一个标准的 POSIX 系统调用,用于创建一个新的空目录。

(图片来源网络,侵删)
函数原型
#include <sys/stat.h> #include <sys/types.h> int mkdir(const char *pathname, mode_t mode);
参数说明
-
pathname(const char *):- 这是一个指向以 null 结尾的字符串的指针,表示你想要创建的目录的路径。
- 路径可以是相对路径(相对于当前工作目录)或绝对路径(从根目录 开始)。
- 如果路径中的任何父目录不存在,
mkdir会直接失败,并返回ENOENT(错误号 2,No such file or directory)。
-
mode(mode_t):- 这个参数用于设置新创建目录的权限。
- 它是一个位掩码,通常用八进制数表示,
0755。 - 权限由三部分组成:所有者、所属组、其他人。
7(rwx): 所有者拥有读、写、执行权限。5(r-x): 所属组拥有读、执行权限。5(r-x): 其他人拥有读、执行权限。
- 重要提示: 最终的权限不仅由
mode参数决定,还会受到进程的 umask 值的影响,实际权限的计算公式为:实际权限 = mode & ~umask。 - 在 Linux 中,目录的执行权限 (
x) 非常重要,它代表“进入”该目录的权限,没有执行权限,你无法cd到该目录中,即使你有读权限。
返回值
- 成功: 返回
0。 - 失败: 返回
-1,并且会设置errno全局变量来指示具体的错误原因,你可以使用perror()函数或strerror(errno)来打印出可读的错误信息。
常见错误码 (errno)
EACCES(错误号 13, Permission denied):- 父目录的写权限被禁止。
- 在文件系统中,
mkdir需要在父目录中拥有写权限,以便创建新的目录项。
EEXIST(错误号 17, File exists):- 由
pathname指定的目录已经存在。
- 由
ENOENT(错误号 2, No such file or directory):路径中的某个父目录不存在。
EROFS(错误号 30, Read-only file system):尝试在一个只读的文件系统上创建目录。
(图片来源网络,侵删)ENOSPC(错误号 28, No space left on device):设备上没有剩余空间了。
示例代码
下面是一些不同场景下的示例代码。
示例 1:创建一个简单的目录
这个例子创建一个名为 my_test_dir 的目录,并设置权限为 0755。
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h> // 用于使用 errno
int main() {
const char *dir_path = "my_test_dir";
mode_t mode = 0755; // 八进制数,注意前缀 0
// 尝试创建目录
if (mkdir(dir_path, mode) == -1) {
// 如果创建失败,打印错误信息
perror("mkdir() failed"); // perror 会自动打印 "mkdir() failed: " 和具体的错误信息
return 1; // 返回非零表示错误
}
printf("Directory '%s' created successfully.\n", dir_path);
return 0;
}
如何编译和运行:

(图片来源网络,侵删)
# 编译 gcc -o mkdir_example mkdir_example.c # 运行 ./mkdir_example # 检查目录是否创建成功以及权限 ls -ld my_test_dir
输出:
Directory 'my_test_dir' created successfully.
drwxr-xr-x 2 user user 4096 Oct 27 10:30 my_test_dir
示例 2:处理错误(例如目录已存在)
这个例子展示了如何处理 EEXIST 错误。
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
int main() {
const char *dir_path = "existing_dir";
mode_t mode = 0700; // 仅所有者有读写执行权限
// 先创建一次
mkdir(dir_path, mode);
// 尝试再次创建
if (mkdir(dir_path, mode) == -1) {
if (errno == EEXIST) {
fprintf(stderr, "Error: Directory '%s' already exists.\n", dir_path);
} else {
perror("mkdir() failed for another reason");
return 1;
}
} else {
printf("Directory '%s' created successfully.\n", dir_path);
}
return 0;
}
示例 3:创建多级目录(mkdir -p 的功能)
标准的 mkdir 函数一次只能创建一级目录,如果父目录不存在,它会失败,要实现类似 mkdir -p 的功能(即如果父目录不存在,则一并创建),你需要自己编写逻辑,或者使用更现代的 mkdirat 配合 open 的 O_DIRECTORY 和 O_EXCL 标志来模拟。
一个简单的方法是递归地检查并创建父目录。
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
// 递归创建多级目录
int create_directory_recursive(const char *path, mode_t mode) {
// 检查路径是否已存在
struct stat st;
if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
return 0; // 目录已存在,无需创建
}
return -1; // 路径存在但不是目录
}
// 如果父目录不存在,则递归创建父目录
char *parent_path = strdup(path); // 复制路径,因为 dirname() 会修改字符串
if (!parent_path) return -1;
char *dir = dirname(parent_path); // 获取父目录路径
if (strcmp(dir, ".") != 0 && strcmp(dir, "/") != 0) {
if (create_directory_recursive(dir, mode) == -1) {
free(parent_path);
return -1;
}
}
free(parent_path);
// 创建当前目录
if (mkdir(path, mode) == -1) {
// 如果错误不是“已存在”,则报告错误
if (errno != EEXIST) {
perror("mkdir() failed");
return -1;
}
}
return 0;
}
int main() {
const char *path = "a/b/c/d";
mode_t mode = 0755;
if (create_directory_recursive(path, mode) == 0) {
printf("Recursive directory creation for '%s' successful.\n", path);
} else {
fprintf(stderr, "Failed to create directory '%s'.\n", path);
return 1;
}
return 0;
}
如何编译和运行:
gcc -o mkdir_recursive mkdir_recursive.c ./mkdir_recursive ls -ld a/b/c/d
现代 C 标准中的替代方案:std::filesystem (C++17)
如果你使用的是 C++17 或更高版本,标准库中提供了一个更安全、更易用的 std::filesystem 库,它不依赖于特定的操作系统 API,是跨平台的,并且功能更强大。
#include <iostream>
#include <filesystem> // C++17 filesystem 库
namespace fs = std::filesystem;
int main() {
fs::path dir_path = "my_cpp_dir";
// 创建单级目录
try {
if (fs::create_directory(dir_path)) {
std::cout << "Directory " << dir_path << " created successfully.\n";
} else {
std::cout << "Directory " << dir_path << " already exists.\n";
}
} catch (const fs::filesystem_error& e) {
std::cerr << "Filesystem error: " << e.what() << '\n';
return 1;
}
// 创建多级目录 (相当于 mkdir -p)
fs::path multi_path = "cpp/a/b/c";
try {
if (fs::create_directories(multi_path)) {
std::cout << "Recursive directory creation for " << multi_path << " successful.\n";
}
} catch (const fs::filesystem_error& e) {
std::cerr << "Filesystem error: " << e.what() << '\n';
return 1;
}
return 0;
}
编译时需要链接 C++ 标准库并支持 C++17:
g++ -std=c++17 -o mkdir_cpp mkdir_cpp.cpp ./mkdir_cpp
| 特性 | mkdir() (POS C) |
std::filesystem (C++17) |
|---|---|---|
| 语言 | C | C++ |
| 标准 | POSIX | ISO C++17 |
| 平台 | 主要是 Unix-like (Linux, macOS) | 跨平台 |
| 创建单级目录 | mkdir(path, mode) |
fs::create_directory(path) |
| 创建多级目录 | 需要自己实现逻辑 | fs::create_directories(path) (内置支持) |
| 错误处理 | 设置 errno,需手动检查 |
抛出 std::filesystem_error 异常 |
| 权限设置 | 通过 mode 参数 |
通过 fs::perms 枚举,与权限掩码结合 |
对于纯 C 语言开发,mkdir() 是标准且高效的选择,如果你有 C++ 的开发环境,强烈推荐使用 std::filesystem,它提供了更现代、更健壮的接口。
