在阅读了具有该名称的Unix系统调用的mkdir(2)手册页之后,该调用似乎没有在路径中创建中间目录,只在路径中创建了最后一个目录。有没有办法(或其他函数)创建路径中的所有目录,而不需要手动解析目录字符串并单独创建每个目录?
发布于 2010-02-26 01:42:14
不幸的是,没有系统调用来为您做这件事。我猜这是因为对于在错误情况下应该发生的事情,没有一种方法可以真正定义好语义。它是否应该保留已经创建的目录?要删除吗?如果删除失败怎么办?以此类推。
然而,创建自己的应用程序是相当容易的,在谷歌上快速搜索“recursive mkdir”就可以找到许多解决方案。这是接近顶端的一个:
http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html
static void _mkdir(const char *dir) {
char tmp[256];
char *p = NULL;
size_t len;
snprintf(tmp, sizeof(tmp),"%s",dir);
len = strlen(tmp);
if (tmp[len - 1] == '/')
tmp[len - 1] = 0;
for (p = tmp + 1; *p; p++)
if (*p == '/') {
*p = 0;
mkdir(tmp, S_IRWXU);
*p = '/';
}
mkdir(tmp, S_IRWXU);
}
发布于 2012-02-09 20:37:28
这是我的解决方案。通过调用下面的函数,您可以确保指向指定文件路径的所有目录都存在。注意,file_path
参数在这里不是目录名,而是您在调用mkpath()
之后将要创建的文件的路径。
例如,如果/home/me/dir/subdir
不存在,mkpath("/home/me/dir/subdir/file.dat", 0755)
将创建它。mkpath("/home/me/dir/subdir/", 0755)
也做同样的事情。
也适用于相对路径。
如果出现错误,则返回-1
并设置errno
。
int mkpath(char* file_path, mode_t mode) {
assert(file_path && *file_path);
for (char* p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
*p = '\0';
if (mkdir(file_path, mode) == -1) {
if (errno != EEXIST) {
*p = '/';
return -1;
}
}
*p = '/';
}
return 0;
}
请注意,file_path
在操作过程中会被修改,但之后会恢复。因此,file_path
并不是严格意义上的const
。
发布于 2013-12-17 21:01:48
这是对mkpath()
的另一种看法,使用递归,它既小又可读。它使用strdupa()
来避免直接更改给定的dir
字符串参数,并避免使用malloc()
& free()
。确保使用-D_GNU_SOURCE
编译以激活strdupa()
...这意味着这段代码只能在GLIBC、EGLIBC、uClibc和其他GLIBC兼容的C库上运行。
int mkpath(char *dir, mode_t mode)
{
if (!dir) {
errno = EINVAL;
return 1;
}
if (strlen(dir) == 1 && dir[0] == '/')
return 0;
mkpath(dirname(strdupa(dir)), mode);
return mkdir(dir, mode);
}
在Inadyn项目中,在这里和来自Valery Frolov的输入之后,现在已经将以下修订版本的mkpath()
推送到libite
int mkpath(char *dir, mode_t mode)
{
struct stat sb;
if (!dir) {
errno = EINVAL;
return 1;
}
if (!stat(dir, &sb))
return 0;
mkpath(dirname(strdupa(dir)), mode);
return mkdir(dir, mode);
}
它又使用了一个syscall,但现在代码更具可读性了。
https://stackoverflow.com/questions/2336242
复制相似问题