如何在C ++ / Linux中创建目录树? [英] How can I create directory tree in C++/Linux?

查看:108
本文介绍了如何在C ++ / Linux中创建目录树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一种简单的方式在C ++ / Linux中创建多个目录。



例如我想在目录中保存一个文件lola.file:

  / tmp / a / b / c 

但是如果目录不在我那里他们被自动创建。一个工作的例子将是完美的。

解决方案

这是一个可以用C ++编译器编译的C函数。
$ b

  / * 
@(#)文件:$ RCSfile:mkpath.c,v $
@(#)版本:$修订:1.13 $
@(#)最后更改:$日期:2012/07/15 00:40:37 $
@(#)目的:创建路径
@ #)作者:J Leffler
@(#)版权所有(C)JLSS 1990-91,1997-98,2001,2005,2008,2012
* /

/ * TABSTOP = 4 * /

#includejlss.h
#includeemalloc.h

#include< errno.h>
#ifdef HAVE_UNISTD_H
#include< unistd.h>
#endif / * HAVE_UNISTD_H * /
#include< string.h>
#includesysstat.h/ *修复Windows - inc mode_t * /

typedef struct stat Stat;

#ifndef lint
/ *防止过度的优化器消除ID字符串* /
const char jlss_id_mkpath_c [] =@(#)$ Id:mkpath.c, v 1.13 2012/07/15 00:40:37 jleffler Exp $;
#endif / * lint * /

static int do_mkdir(const char * path,mode_t mode)
{
Stat st;
int status = 0;

if(stat(path,& st)!= 0)
{
/ *目录不存在。 EEXIST竞争条件* /
if(mkdir(path,mode)!= 0&& errno!= EEXIST)
status = -1;
}
else if(!S_ISDIR(st.st_mode))
{
errno = ENOTDIR;
status = -1;
}

return(status);
}

/ **
** mkpath - 确保路径中的所有目录都存在
**算法采用悲观视图,并自上而下确保
**路径中的每个目录都存在,而不是乐观地创建
**最后一个元素并向后工作。
* /
int mkpath(const char * path,mode_t mode)
{
char * pp;
char * sp;
int status;
char * copypath = STRDUP(path);

status = 0;
pp = copypath;
while(status == 0&&(sp = strchr(pp,'/'))!= 0)
{
if(sp!= pp)
{
/ *路径* /
* sp ='\0'中的根或双斜线;
status = do_mkdir(copypath,mode);
* sp ='/';
}
pp = sp + 1;
}
if(status == 0)
status = do_mkdir(path,mode);
FREE(copypath);
return(status);
}

#ifdef TEST

#include< stdio.h>

/ *
**压力测试并行运行mkpath()函数。
**在EEXIST测试之前,代码将失败。
**使用EEXIST测试,代码不会失败。
**
**测试shell脚本
** PREFIX = mkpath。$$
** NAME =。/ $ PREFIX / sa / 32 / ad / 13/23 / 13/12/13 / sd / ds / ww / qq / ss / dd / zz / xx / dd / rr / ff / ff / ss / ss / ss / ss / ss / ss / ss / ss
* *:$ {MKPATH:= mkpath}
** ./$MKPATH $ NAME&
** [...重复十几次...]
** ./$MKPATH $ NAME&
**等待
** rm -fr ./$PREFIX/
* /

int main(int argc,char ** argv)
{
int i; (i = 1; i< argc; i ++)


{
for(int j = 0; j< 20; j ++)
{
if(fork()== 0)
{
int rc = mkpath(argv [i],0777);
if(rc!= 0)
fprintf(stderr,%d:无法创建(%d:%s):%s\\\

(int)getpid ),errno,strerror(errno),argv [i]);
exit(rc == 0?EXIT_SUCCESS:EXIT_FAILURE);
}
}
int status;
int fail = 0;
while(wait(& status)!= -1)
{
if(WEXITSTATUS(status)!= 0)
fail = 1;
}
if(fail == 0)
printf(created:%s\\\
,argv [i]);
}
return(0);
}

#endif / * TEST * /

STRDUP() FREE()是错误检查版本的 strdup() free(),在 emalloc.h 中声明(并在 emalloc.c estrdup.c )。 sysstat.h头处理< sys / stat.h> 的破坏版本,可以替换在现代的Unix系统上由$ code>< sys / stat.h> (但在1990年出现了许多问题)。而jlss.h声明 mkpath()



v1.12(上一个)和v1.13(以上)之间的变化是 do_mkdir() EEXIST 的测试$ C>。根据需要切换—谢谢你,Switch。测试代码已经升级并重现了MacBook Pro(2.3GHz Intel Core i7,运行Mac OS X 10.7.4)上的问题,并建议在修订中修复问题(但测试只能显示错误的存在,不要缺席)。



(特此授予您允许使用此代码进行任何归因归属)。


I want an easy way to create multiple directories in C++/Linux.

For example I want to save a file lola.file in the directory:

/tmp/a/b/c

but if the directories are not there I want them to be created automagically. A working example would be perfect.

解决方案

Here's a C function that can be compiled with C++ compilers.

/*
@(#)File:           $RCSfile: mkpath.c,v $
@(#)Version:        $Revision: 1.13 $
@(#)Last changed:   $Date: 2012/07/15 00:40:37 $
@(#)Purpose:        Create all directories in path
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 1990-91,1997-98,2001,2005,2008,2012
*/

/*TABSTOP=4*/

#include "jlss.h"
#include "emalloc.h"

#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <string.h>
#include "sysstat.h"    /* Fix up for Windows - inc mode_t */

typedef struct stat Stat;

#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_mkpath_c[] = "@(#)$Id: mkpath.c,v 1.13 2012/07/15 00:40:37 jleffler Exp $";
#endif /* lint */

static int do_mkdir(const char *path, mode_t mode)
{
    Stat            st;
    int             status = 0;

    if (stat(path, &st) != 0)
    {
        /* Directory does not exist. EEXIST for race condition */
        if (mkdir(path, mode) != 0 && errno != EEXIST)
            status = -1;
    }
    else if (!S_ISDIR(st.st_mode))
    {
        errno = ENOTDIR;
        status = -1;
    }

    return(status);
}

/**
** mkpath - ensure all directories in path exist
** Algorithm takes the pessimistic view and works top-down to ensure
** each directory in path exists, rather than optimistically creating
** the last element and working backwards.
*/
int mkpath(const char *path, mode_t mode)
{
    char           *pp;
    char           *sp;
    int             status;
    char           *copypath = STRDUP(path);

    status = 0;
    pp = copypath;
    while (status == 0 && (sp = strchr(pp, '/')) != 0)
    {
        if (sp != pp)
        {
            /* Neither root nor double slash in path */
            *sp = '\0';
            status = do_mkdir(copypath, mode);
            *sp = '/';
        }
        pp = sp + 1;
    }
    if (status == 0)
        status = do_mkdir(path, mode);
    FREE(copypath);
    return (status);
}

#ifdef TEST

#include <stdio.h>

/*
** Stress test with parallel running of mkpath() function.
** Before the EEXIST test, code would fail.
** With the EEXIST test, code does not fail.
**
** Test shell script
** PREFIX=mkpath.$$
** NAME=./$PREFIX/sa/32/ad/13/23/13/12/13/sd/ds/ww/qq/ss/dd/zz/xx/dd/rr/ff/ff/ss/ss/ss/ss/ss/ss/ss/ss
** : ${MKPATH:=mkpath}
** ./$MKPATH $NAME &
** [...repeat a dozen times or so...]
** ./$MKPATH $NAME &
** wait
** rm -fr ./$PREFIX/
*/

int main(int argc, char **argv)
{
    int             i;

    for (i = 1; i < argc; i++)
    {
        for (int j = 0; j < 20; j++)
        {
            if (fork() == 0)
            {
                int rc = mkpath(argv[i], 0777);
                if (rc != 0)
                    fprintf(stderr, "%d: failed to create (%d: %s): %s\n",
                            (int)getpid(), errno, strerror(errno), argv[i]);
                exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
            }
        }
        int status;
        int fail = 0;
        while (wait(&status) != -1)
        {
            if (WEXITSTATUS(status) != 0)
                fail = 1;
        }
        if (fail == 0)
            printf("created: %s\n", argv[i]);
    }
    return(0);
}

#endif /* TEST */

The macros STRDUP() and FREE() are error-checking versions of strdup() and free(), declared in emalloc.h (and implemented in emalloc.c and estrdup.c). The "sysstat.h" header deals with broken versions of <sys/stat.h> and can be replaced by <sys/stat.h> on modern Unix systems (but there were many issues back in 1990). And "jlss.h" declares mkpath().

The change between v1.12 (previous) and v1.13 (above) is the test for EEXIST in do_mkdir(). This was pointed out as necessary by Switch — thank you, Switch. The test code has been upgraded and reproduced the problem on a MacBook Pro (2.3GHz Intel Core i7, running Mac OS X 10.7.4), and suggests that the problem is fixed in the revision (but testing can only show the presence of bugs, never their absence).

(You are hereby given permission to use this code for any purpose with attribution.)

这篇关于如何在C ++ / Linux中创建目录树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆