首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Unix上的递归mkdir()系统调用

Unix上的递归mkdir()系统调用
EN

Stack Overflow用户
提问于 2010-02-26 01:41:47
回答 12查看 107.6K关注 0票数 73

在阅读了具有该名称的Unix系统调用的mkdir(2)手册页之后,该调用似乎没有在路径中创建中间目录,只在路径中创建了最后一个目录。有没有办法(或其他函数)创建路径中的所有目录,而不需要手动解析目录字符串并单独创建每个目录?

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2010-02-26 01:42:14

不幸的是,没有系统调用来为您做这件事。我猜这是因为对于在错误情况下应该发生的事情,没有一种方法可以真正定义好语义。它是否应该保留已经创建的目录?要删除吗?如果删除失败怎么办?以此类推。

然而,创建自己的应用程序是相当容易的,在谷歌上快速搜索“recursive mkdir”就可以找到许多解决方案。这是接近顶端的一个:

http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html

代码语言:javascript
复制
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);
}
票数 103
EN

Stack Overflow用户

发布于 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

代码语言:javascript
复制
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

票数 29
EN

Stack Overflow用户

发布于 2013-12-17 21:01:48

这是对mkpath()的另一种看法,使用递归,它既小又可读。它使用strdupa()来避免直接更改给定的dir字符串参数,并避免使用malloc() & free()。确保使用-D_GNU_SOURCE编译以激活strdupa() ...这意味着这段代码只能在GLIBC、EGLIBC、uClibc和其他GLIBC兼容的C库上运行。

代码语言:javascript
复制
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

代码语言:javascript
复制
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,但现在代码更具可读性了。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2336242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档