【问题标题】:How can I create directory tree in C++/Linux?如何在 C++/Linux 中创建目录树?
【发布时间】:2010-10-15 01:45:07
【问题描述】:

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

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

/tmp/a/b/c

但如果目录不存在,我希望它们自动创建。一个工作示例将是完美的。

【问题讨论】:

  • C++本身没有任何用于创建目录和树的内置工具。您将不得不使用 C 和系统调用或像 Boost 这样的外部库。 C 和系统调用将取决于平台。
  • @noloader 非常感谢.. 但我认为 4 年后我几乎得到了答案,正如您在下面以 13 种不同的方式看到的那样......
  • 是的,我很惊讶没有人明确声明你不能在 C++ 中做到这一点(假设你想要一个在 Linux 上工作的 C++ 中的可移植方法)。但你可能知道;)。不过,对于不可移植的 C 代码,有很多很好的建议。
  • 什么是“C++/Linux”?
  • @LightnessRacesinOrbit 这是我在 Linux 上使用 C++ 的大学时光 :)

标签: c++ linux directory


【解决方案1】:

如果您还没有 C++17 并且正在寻找与平台无关的解决方案,请使用 ghc::filesystem。仅标头代码与 C++17 兼容(实际上是一个向后移植),并且以后易于迁移。

【讨论】:

    【解决方案2】:

    对于 C++17 或更高版本,标准头 <filesystem> 带有 功能 std::filesystem::create_directories 应该在现代 C++ 程序中使用。 C++ 标准函数没有特定于 POSIX 的显式 不过,权限(模式)参数。

    但是,这里有一个可以用 C++ 编译器编译的 C 函数。

    /*
    @(#)File:           mkpath.c
    @(#)Purpose:        Create all directories in path
    @(#)Author:         J Leffler
    @(#)Copyright:      (C) JLSS 1990-2020
    @(#)Derivation:     mkpath.c 1.16 2020/06/19 15:08:10
    */
    
    /*TABSTOP=4*/
    
    #include "posixver.h"
    #include "mkpath.h"
    #include "emalloc.h"
    
    #include <errno.h>
    #include <string.h>
    /* "sysstat.h" == <sys/stat.h> with fixup for (old) Windows - inc mode_t */
    #include "sysstat.h"
    
    typedef struct stat Stat;
    
    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>
    #include <unistd.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 */
    

    STRDUP()FREE()strdup()free(),在 emalloc.h 中声明(并在 emalloc.cestrdup.c)。 "sysstat.h" 标头处理 &lt;sys/stat.h&gt; 的损坏版本 并且可以在现代 Unix 系统上被 &lt;sys/stat.h&gt; 替换(但有 早在 1990 年就有很多问题)。 "mkpath.h" 声明 mkpath()

    v1.12(答案的原始版本)和v1.13之间的变化 (答案的修改版本)是对EEXIST 的测试 do_mkdir()。 有人指出这是必要的 Switch — 谢谢 你,开关。 测试代码已升级并在MacBook上重现问题 Pro(2.3GHz Intel Core i7,运行 Mac OS X 10.7.4),并建议 该问题已在修订版中修复(但测试只能显示 错误的存在,从来没有他们的缺席)。 显示的代码现在是 v1.16;有化妆品或行政 自 v1.13 以来所做的更改(例如使用 mkpath.h 而不是 jlss.h 和 仅在测试代码中无条件地包含&lt;unistd.h&gt;)。 有理由认为 "sysstat.h" 应该替换为 &lt;sys/stat.h&gt; 除非你有一个异常顽固的系统。

    (特此允许您出于任何目的使用此代码并注明出处。)

    此代码可在我的SOQ 中找到 (堆栈溢出问题)GitHub 上的存储库作为文件mkpath.cmkpath.h(等)在 src/so-0067-5039 子目录。

    【讨论】:

    • 肯定比系统快。系统涉及很多开销。基本上,必须分叉该进程,然后必须加载至少两个二进制文件(一个可能已经在缓存中),其中一个将是另一个的另一个分叉,...
    • 我忘记了:然后“mkdir -p”将至少与上面发布的代码相同!
    • 这段代码中有一个微妙的竞争条件,我实际上遇到了。只有当多个程序同时启动并创建相同的文件夹路径时才会发生这种情况。修复方法是在 mkdir 失败时添加 if (errno != EEXIST) { status = -1; }
    • @Switch:谢谢。这就是在mkdir() 之前使用stat() 的问题;这是一个TOCTOU(检查时间,使用时间)问题。我尝试用一​​个在后台运行 13 个进程的 shell 脚本来解决这个错误,创建相同的 29 元素路径,但没有成功。然后我破解了测试程序 20 次 fork 并让每个孩子都尝试,并且成功地解决了这个错误。固定代码将有if (mkdir(path, mode) != 0 &amp;&amp; errno != EEXIST) status = -1;。这并没有显示错误。
    • @DavidMerinos:它们是标题(jlss.hemalloc.h),而不是库。但是,该代码可在 GitHub 上的 SOQ(堆栈溢出问题)存储库中以文件 jlss.hemalloc.cemalloc.h 的形式在 src/libsoq 子目录中找到。你还需要posixver.h,还有其他一些(debug.hstderr.cstderr.h——我想就是这样,但你需要的都应该在那个目录中)。
    【解决方案3】:

    这是使用dirname() 自下而上遍历目录树的C/C++ 递归函数。一旦找到现有的祖先,它就会停止。

    #include <libgen.h>
    #include <string.h>
    
    int create_dir_tree_recursive(const char *path, const mode_t mode)
    {
        if (strcmp(path, "/") == 0) // No need of checking if we are at root.
            return 0;
    
        // Check whether this dir exists or not.
        struct stat st;
        if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode))
        {
            // Check and create parent dir tree first.
            char *path2 = strdup(path);
            char *parent_dir_path = dirname(path2);
            if (create_dir_tree_recursive(parent_dir_path, mode) == -1)
                return -1;
    
            // Create this dir.
            if (mkdir(path, mode) == -1)
                return -1;
        }
    
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      这里已经描述了很多方法,但其中大多数都需要将路径硬编码到代码中。 这个问题有一个简单的解决方案,使用 QDir 和 QFileInfo 这两个 Qt 框架类。由于您已经在 Linux 环境中,所以应该很容易使用 Qt。

      QString qStringFileName("path/to/the/file/that/dont/exist.txt");
      QDir dir = QFileInfo(qStringFileName).dir();
      if(!dir.exists()) {
              dir.mkpath(dir.path());
      }
      

      确保您对该路径具有写入权限。

      【讨论】:

        【解决方案5】:

        这类似于前面的,但通过字符串向前而不是向后递归。将 errno 保留为上次失败的正确值。如果有一个前导斜线,则通过循环会有额外的时间,这可以通过循环外的一个 find_first_of() 或通过检测前导 / 并将 pre 设置为 1 来避免。无论我们是由 a 设置的,效率都是相同的第一个循环或预循环调用,使用预循环调用时复杂度会(略)高。

        #include <iostream>
        #include <string>
        #include <sys/stat.h>
        
        int
        mkpath(std::string s,mode_t mode)
        {
            size_t pos=0;
            std::string dir;
            int mdret;
        
            if(s[s.size()-1]!='/'){
                // force trailing / so we can handle everything in loop
                s+='/';
            }
        
            while((pos=s.find_first_of('/',pos))!=std::string::npos){
                dir=s.substr(0,pos++);
                if(dir.size()==0) continue; // if leading / first time is 0 length
                if((mdret=mkdir(dir.c_str(),mode)) && errno!=EEXIST){
                    return mdret;
                }
            }
            return mdret;
        }
        
        int main()
        {
            int mkdirretval;
            mkdirretval=mkpath("./foo/bar",0755);
            std::cout << mkdirretval << '\n';
        
        }
        

        【讨论】:

          【解决方案6】:

          需要注意的是,从 C++17 开始,文件系统接口是标准库的一部分。这意味着可以有以下创建目录:

          #include <filesystem>
          
          std::filesystem::create_directories("/a/b/c/d")
          

          更多信息在这里:https://en.cppreference.com/w/cpp/filesystem/create_directory

          此外,使用 gcc,需要将“-std=c++17”设置为 CFLAGS。和“-lstdc++fs”到 LDLIBS。未来可能不需要后者。

          【讨论】:

          【解决方案7】:
          system("mkdir -p /tmp/a/b/c")
          

          是我能想到的最短方式(就代码长度而言,不一定是执行时间)。

          它不是跨平台的,但可以在 Linux 下运行。

          【讨论】:

          • 如果您将解决方案作为 shell 命令提供,最好提及 system (3)
          • 不要忘记,如果路径不受您控制,您需要正确地转义路径。否则会造成巨大的安全漏洞。
          • 我想知道为什么人们在 WinAPI 和 Libc 中创建这么多 API,而您可以使用系统创建整个程序。说真的,为什么这篇文章有 42 个赞,这是一个主要的安全问题和一个糟糕的编程习惯。
          【解决方案8】:

          如果目录不存在,则创建它:

          boost::filesystem::create_directories(boost::filesystem::path(output_file).parent_path().string().c_str()); 
          

          【讨论】:

            【解决方案9】:

            这是我的代码示例(适用于 Windows 和 Linux):

            #include <iostream>
            #include <string>
            #include <sys/stat.h> // stat
            #include <errno.h>    // errno, ENOENT, EEXIST
            #if defined(_WIN32)
            #include <direct.h>   // _mkdir
            #endif
            
            bool isDirExist(const std::string& path)
            {
            #if defined(_WIN32)
                struct _stat info;
                if (_stat(path.c_str(), &info) != 0)
                {
                    return false;
                }
                return (info.st_mode & _S_IFDIR) != 0;
            #else 
                struct stat info;
                if (stat(path.c_str(), &info) != 0)
                {
                    return false;
                }
                return (info.st_mode & S_IFDIR) != 0;
            #endif
            }
            
            bool makePath(const std::string& path)
            {
            #if defined(_WIN32)
                int ret = _mkdir(path.c_str());
            #else
                mode_t mode = 0755;
                int ret = mkdir(path.c_str(), mode);
            #endif
                if (ret == 0)
                    return true;
            
                switch (errno)
                {
                case ENOENT:
                    // parent didn't exist, try to create it
                    {
                        int pos = path.find_last_of('/');
                        if (pos == std::string::npos)
            #if defined(_WIN32)
                            pos = path.find_last_of('\\');
                        if (pos == std::string::npos)
            #endif
                            return false;
                        if (!makePath( path.substr(0, pos) ))
                            return false;
                    }
                    // now, try to create again
            #if defined(_WIN32)
                    return 0 == _mkdir(path.c_str());
            #else 
                    return 0 == mkdir(path.c_str(), mode);
            #endif
            
                case EEXIST:
                    // done!
                    return isDirExist(path);
            
                default:
                    return false;
                }
            }
            
            int main(int argc, char* ARGV[])
            {
                for (int i=1; i<argc; i++)
                {
                    std::cout << "creating " << ARGV[i] << " ... " << (makePath(ARGV[i]) ? "OK" : "failed") << std::endl;
                }
                return 0;
            }
            

            用法:

            $ makePath 1/2 folderA/folderB/folderC
            creating 1/2 ... OK
            creating folderA/folderB/folderC ... OK
            

            【讨论】:

            • 我赞同该评论! (令人惊讶的是)找到一种可移植的 C++ 方法来创建目录并非易事。这个答案需要更多的支持。
            • 在 Windows 下,如果尾随字符是反斜杠,isDirExist 不起作用。总是返回假。我必须将代码修改为: std::string dirPath(path); while ('\\' == *dirPath.rbegin()) dirPath.pop_back(); ...然后,当然,在对 _stat 的调用中传递 dirPath.c_str()。
            • Windows API 对stat(与__STDC__ 相关)具有“非ANSI 名称以实现兼容性”,无需预编译器测试。
            【解决方案10】:

            所以我今天需要mkdirp(),发现此页面上的解决方案过于复杂。 因此我写了一个相当短的 sn-p,很容易被其他人复制 偶然发现这个线程,奇怪为什么我们需要这么多行代码。

            mkdirp.h

            #ifndef MKDIRP_H
            #define MKDIRP_H
            
            #include <sys/stat.h>
            
            #define DEFAULT_MODE      S_IRWXU | S_IRGRP |  S_IXGRP | S_IROTH | S_IXOTH
            
            /** Utility function to create directory tree */
            bool mkdirp(const char* path, mode_t mode = DEFAULT_MODE);
            
            #endif // MKDIRP_H
            

            mkdirp.cpp

            #include <errno.h>
            
            bool mkdirp(const char* path, mode_t mode) {
              // const cast for hack
              char* p = const_cast<char*>(path);
            
              // Do mkdir for each slash until end of string or error
              while (*p != '\0') {
                // Skip first character
                p++;
            
                // Find first slash or end
                while(*p != '\0' && *p != '/') p++;
            
                // Remember value from p
                char v = *p;
            
                // Write end of string at p
                *p = '\0';
            
                // Create folder from path to '\0' inserted at p
                if(mkdir(path, mode) == -1 && errno != EEXIST) {
                  *p = v;
                  return false;
                }
            
                // Restore path to it's former glory
                *p = v;
              }
            
              return true;
            }
            

            如果您不喜欢 const 转换和临时修改字符串,只需在之后执行 strdup()free()

            【讨论】:

            • 也发到gist了,下次有需要的时候别忘了放哪里:)gist.github.com/jonasfj/7797272
            • 尝试修改作为常量传递的字符串是邪恶的。除此之外,如果它曾经传递一个字符串文字,它可能会导致严重的失败。
            • 完全正确....这实际上很糟糕...可能 strcpy 会使它变得更好...
            【解决方案11】:

            使用 Boost.Filesystem 轻松实现:create_directories

            #include <boost/filesystem.hpp>
            //...
            boost::filesystem::create_directories("/tmp/a/b/c");
            

            如果创建了新目录,则返回:true,否则返回false

            【讨论】:

            • 嗯,大多数 boost 库都是只有头文件的,这意味着除了你使用的东西之外没有任何开销。在 Boost.Filesystem 的情况下,它需要编译。在我的磁盘上,编译后的库重约 60KB。
            • @Lipis:请准确说明您的嵌入式系统是什么。我相信它应该适用于几乎所有的 Linux 发行版。
            • 关于@danijar 提到的C++11 编译器,here 的评论说得更清楚了:The &lt;filesystem&gt; header is not part of C++11; it is a proposal for C++ TR2 based on the Boost.Filesystem library. Visual C++ 2012 includes an implementation of the proposed library.
            • boost::filesystem 不是仅标头:stackoverflow.com/questions/13604090/…
            • 恕我直言:在我的任何打算做一些重要的事情并经受住时间考验的项目中,拥有像 boost 这样一组非常有用和强大的标准化工具是非常值得编译的。其中很多已经进入标准 C++,当然还会有更多。试一试,坚持下去,如果你有比琐碎的需求而且你不想重新发明轮子,你会受益。 :-)
            【解决方案12】:

            我知道这是一个老问题,但它在 google 搜索结果中显示很高,这里提供的答案不是真正的 C++ 或有点太复杂。

            请注意,在我的示例中 createDirTree() 非常简单,因为无论如何所有繁重的工作(错误检查、路径验证)都需要由 createDir() 完成。如果目录已经存在或者整个事情都不起作用,createDir() 也应该返回 true。

            这是我在 C++ 中的做法:

            #include <iostream>
            #include <string>
            
            bool createDir(const std::string dir)
            {
                std::cout << "Make sure dir is a valid path, it does not exist and create it: "
                          << dir << std::endl;
                return true;
            }
            
            bool createDirTree(const std::string full_path)
            {
                size_t pos = 0;
                bool ret_val = true;
            
                while(ret_val == true && pos != std::string::npos)
                {
                    pos = full_path.find('/', pos + 1);
                    ret_val = createDir(full_path.substr(0, pos));
                }
            
                return ret_val;
            }
            
            int main()
            {
                createDirTree("/tmp/a/b/c");
                return 0;
            }
            

            当然 createDir() 函数将是系统特定的,其他答案中已经有足够多的示例如何为 linux 编写它,所以我决定跳过它。

            【讨论】:

              【解决方案13】:

              由于这篇文章在“创建目录树”方面在 Google 中的排名很高,我将发布一个适用于 Windows 的答案——这将使用为 UNICODE 或 MBCS 编译的 Win32 API 工作。这是从上面 Mark 的代码移植过来的。

              由于我们使用的是 Windows,目录分隔符是反斜杠,而不是正斜杠。如果您希望使用正斜杠,请将 '\\' 更改为 '/'

              它适用于:

              c:\foo\bar\hello\world
              

              c:\foo\bar\hellp\world\
              

              (即:不需要斜杠,因此您不必检查它。)

              在说“只需在 Windows 中使用 SHCreateDirectoryEx()”之前,请注意 SHCreateDirectoryEx() 已被弃用,并且可以随时从未来的 Windows 版本中删除。

              bool CreateDirectoryTree(LPCTSTR szPathTree, LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL){
                  bool bSuccess = false;
                  const BOOL bCD = CreateDirectory(szPathTree, lpSecurityAttributes);
                  DWORD dwLastError = 0;
                  if(!bCD){
                      dwLastError = GetLastError();
                  }else{
                      return true;
                  }
                  switch(dwLastError){
                      case ERROR_ALREADY_EXISTS:
                          bSuccess = true;
                          break;
                      case ERROR_PATH_NOT_FOUND:
                          {
                              TCHAR szPrev[MAX_PATH] = {0};
                              LPCTSTR szLast = _tcsrchr(szPathTree,'\\');
                              _tcsnccpy(szPrev,szPathTree,(int)(szLast-szPathTree));
                              if(CreateDirectoryTree(szPrev,lpSecurityAttributes)){
                                  bSuccess = CreateDirectory(szPathTree,lpSecurityAttributes)!=0;
                                  if(!bSuccess){
                                      bSuccess = (GetLastError()==ERROR_ALREADY_EXISTS);
                                  }
                              }else{
                                  bSuccess = false;
                              }
                          }
                          break;
                      default:
                          bSuccess = false;
                          break;
                  }
              
                  return bSuccess;
              }
              

              【讨论】:

              • 一个小mod - 如果路径包含反斜杠,这不起作用。这里: ` LPCTSTR szLast = _tcsrchr(szPathTree, '\\');` 你只需要添加这个: ``` if (nullptr == szLast) { szLast = _tcsrchr(szPathTree, '/'); } ```
              • 感谢您的信息。如果路径是混合的会发生什么?即:c:\this\is\a/mixed/path\of\slashes 通常 Windows 斜杠是反斜杠。应该发生的是调用者应该在调用此方法之前清理路径并确保所有斜线都是正确的。
              【解决方案14】:
              bool mkpath( std::string path )
              {
                  bool bSuccess = false;
                  int nRC = ::mkdir( path.c_str(), 0775 );
                  if( nRC == -1 )
                  {
                      switch( errno )
                      {
                          case ENOENT:
                              //parent didn't exist, try to create it
                              if( mkpath( path.substr(0, path.find_last_of('/')) ) )
                                  //Now, try to create again.
                                  bSuccess = 0 == ::mkdir( path.c_str(), 0775 );
                              else
                                  bSuccess = false;
                              break;
                          case EEXIST:
                              //Done!
                              bSuccess = true;
                              break;
                          default:
                              bSuccess = false;
                              break;
                      }
                  }
                  else
                      bSuccess = true;
                  return bSuccess;
              }
              

              【讨论】:

              • 这对我来说是最好的解决方案!谢谢!)))
              • 也许这是一个转储问题,但是 mkdir 之前的“::”前缀是什么?
              • 找到了答案,:: 确保解析发生在全局命名空间stackoverflow.com/questions/4269034/…
              【解决方案15】:
              mkdir -p /dir/to/the/file
              
              touch /dir/to/the/file/thefile.ending
              

              【讨论】:

              • -p 选项是我正在寻找的。谢谢!
              【解决方案16】:
              #include <sys/types.h>
              #include <sys/stat.h>
              
              int status;
              ...
              status = mkdir("/tmp/a/b/c", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
              

              来自here。您可能必须为 /tmp、/tmp/a、/tmp/a/b/ 和 /tmp/a/b/c 执行单独的 mkdir,因为 C api 中没有 -p 标志的等效项。在执行更高级别的操作时,请务必忽略 EEXISTS errno。

              【讨论】:

              • 有趣的事实:至少 Solaris 和 HP/UX 有 mkdirp(),尽管它显然不是最佳的可移植性。
              • 这就是重点..我不想单独调用所有这些函数。
              • 调用 mkdir 几次会比调用一次 system 快得多。
              • 我不明白你的建议:用不同的参数调用 mkdir 4 次? ("/tmp/",...)("/tmp/a/",...)("/tmp/a/b/",...)("/tmp/a/b/c/",...)
              • 再一次,同样的调用 3 次非常简单。关键是要给人们足够的信息,让他们可以编写代码,而不是为他们编写代码。
              【解决方案17】:

              你说的是“C++”,但这里的每个人似乎都在想“Bash shell”。

              查看gnu的源代码mkdir;然后你可以看到如何在 C++ 中实现 shell 命令。

              【讨论】:

              • 那么 system("mkdir...") 应该可以在 linux 上解决问题。不过它不是跨平台的。
              • 我赞同@MartinCarpenter 所说的
              • 这个问题令人困惑......
              【解决方案18】:

              其他人给了你正确的答案,但我想我会展示你可以做的另一件巧妙的事情:

              mkdir -p /tmp/a/{b,c}/d
              

              将创建以下路径:

              /tmp/a/b/d
              /tmp/a/c/d
              

              大括号允许您在层次结构的同一级别上一次创建多个目录,而-p 选项表示“根据需要创建父目录”。

              【讨论】:

              • 看到保罗的回答后,我意识到我(和很多其他人)误解了这个问题......
              • 如果有人可以通过更改为 system("mkdir -p /tmp/a/{b,c}/d") 来更新它,因为问题不在于在 shell 中进行。但是通过 C++。
              • 我认为 {a,b} 可以在 sh 派生和 csh 派生的 shell 中工作。不过,我不确定它是否可以在 system() 命令中使用。
              • @Lipis:通过 system() 这样做并不是解决 OP 问题的好方法。 @Andy:我以前从未考虑过,但我只是通过用“echo”替换“mkdir -p”来测试它,它打印出“/tmp/a/b/d /tmp/a/c/d”,这表明它是 shell 做的,而不是 mkdir。
              • @rmeador:如果这不是一个好的解决方案,您还有其他建议吗?我想通过 C++ 做到这一点......这是我的问题,而不是如何通过 shell 做到这一点......
              猜你喜欢
              • 1970-01-01
              • 2023-03-14
              • 2013-08-16
              • 1970-01-01
              • 2012-02-14
              • 2014-08-27
              • 2011-12-18
              • 1970-01-01
              相关资源
              最近更新 更多