Як я можу створити дерево каталогів у C ++ / Linux?


109

Я хочу простий спосіб створення декількох каталогів на C ++ / Linux.

Наприклад, я хочу зберегти файл lola.file у каталозі:

/tmp/a/b/c

але якщо каталогів немає, я хочу їх створити автоматично. Робочий приклад був би ідеальним.


C ++ не має будь-яких вбудованих засобів для створення каталогів і дерев , які самі по собі . Вам доведеться використовувати C та системні дзвінки або зовнішню бібліотеку типу Boost. C та системні виклики залежать від платформи.
jww

6
@noloader Спасибі багато чоловіка .. але я думаю, що через 4 роки я дуже отримав свою відповідь, як ви бачите нижче 13 різними способами ...
Ліпіс

Так, я був здивований, що ніхто прямо не заявив, що ви не можете це зробити на C ++ (якщо припустити, що ви хочете портативний метод на C ++, який працює в Linux). Але ви, напевно, це знали;). Однак було багато хороших пропозицій щодо портативного коду С.
jww

Що таке "C ++ / Linux"?
Гонки легкості на орбіті

3
@LightnessRacesinOrbit Це мої університетські роки на C ++ на Linux :)
Ліпіс,

Відповіді:


59

З 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.cта estrdup.c). У "sysstat.h"справі заголовка з зламаними версіями <sys/stat.h> і може бути замінено <sys/stat.h>на сучасних системах Unix (але є багато питань , ще в 1990 році). І "mkpath.h"заявляє mkpath().

Перевірка між v1.12 (оригінальна версія відповіді) та v1.13 (змінена версія відповіді) була тестом на EEXISTв do_mkdir(). Це вказало на необхідність Switch - спасибі, Switch. Тестовий код було оновлено та відтворено проблему на MacBook Pro (2.3 ГГц Intel Core i7, що працює під керуванням Mac OS X 10.7.4), і передбачає, що проблема виправлена ​​в редакції (але тестування може показувати лише наявність помилок , ніколи їх відсутність). Показаний код тепер v1.16; відбулися косметичні чи адміністративні зміни з часу v1.13 (такі як використання mkpath.hзамість jlss.hі <unistd.h>безумовно включати лише у тестовий код). Доцільно стверджувати, що його "sysstat.h"слід замінити, <sys/stat.h>якщо у вас немає незвично непокірної системи.

(Ви надаєте дозвіл використовувати цей код для будь-яких цілей з атрибуцією.)

Цей код доступний у моєму сховищі SOQ (Питання переповнення стека) у GitHub у вигляді файлів mkpath.cта mkpath.h(тощо) у підкаталозі src / so-0067-5039 .


2
Це, безумовно, швидше, ніж система. У системі багато задіяних накладних витрат. В основному, процес слід розщедрити, тоді потрібно завантажити щонайменше два двійкові файли (одна, мабуть, уже буде в кеші), на якій буде ще одна вилка іншої, ...
ypnos

1
Я забув: І тоді "mkdir -p" зробить принаймні те саме, що і код, розміщений вище!
ypnos

7
У цьому коді є тонка умова гонки, яку я фактично вразив. Це відбувається лише тоді, коли одночасно запускається кілька програм і роблять один і той же шлях до папки. Виправлення - додавати, if (errno != EEXIST) { status = -1; }коли mkdir не працює.
Вимкнути

2
@Switch: Дякую Ось проблема з використанням stat()раніше mkdir(); це проблема TOCTOU (час перевірки, час використання). Я спробував відмітити помилку скриптом оболонки, який виконує 13 процесів у фоновому режимі, створюючи той самий 29-елементний шлях, і не вдалося його вдарити. Тоді я зламав тестову програму, щоб розщедритися 20 разів, і кожну дитину спробувати, і це вдалося потрапити на помилку. Фіксований код матиме if (mkdir(path, mode) != 0 && errno != EEXIST) status = -1;. Це не показує помилку.
Джонатан Леффлер

2
@DavidMerinos: вони заголовки ( jlss.h, emalloc.h), а не бібліотеки. Тим НЕ менше, код доступний в моєму SOQ (переповнення стека Питання) репозиторій на GitHub в вигляді файлів jlss.h, emalloc.cі emalloc.hв SRC / libsoq підкаталозі. Вам потрібно posixver.hтакож, і кілька інших ( debug.h, stderr.c, stderr.h- я думаю , що це, але то , що вам потрібно все повинні бути в цьому каталозі).
Джонатан Леффлер

157

Легко за допомогою Boost.Filesystem: create_directories

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

Повертає: trueякщо створено новий каталог, в іншому випадку false.


9
Ну, більшість прискорених бібліотек є лише заголовками, тобто немає накладних витрат, крім того, що ви використовуєте. У випадку Boost.Filesystem він вимагає компіляції. На моєму диску складена бібліотека важить ~ 60 КБ.
Беньот

1
@Lipis: уточніть, будь ласка, що ваша вбудована система. Я вважаю, що він повинен бути доступний майже у кожному дистрибутиві Linux.
Benoît

4
Щодо компіляторів C ++ 11, згаданих @danijar, коментар тут став більш зрозумілим: The <filesystem> 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.
Chunliang Lyu

5
підвищення :: файлову систему не заголовок тільки: stackoverflow.com/questions/13604090 / ...
ftvs

2
ІМХО: У будь-якому моєму проекті, який покликаний зробити щось значне і витримати тест на час, ДОБРЕ варто складати такий набір неймовірно корисних і потужних стандартизованих інструментів, як підвищення. Тонна його вже пробилася в стандартний C ++, безумовно, ще багато. Спробуйте, дотримуйтесь цього, ви отримаєте користь, якщо у вас більше тривіальних потреб і ви не хочете винаходити колесо. :-)
moodboom

42
system("mkdir -p /tmp/a/b/c")

це найкоротший спосіб, про який я можу придумати (з точки зору тривалості коду, не обов'язково часу виконання).

Це не крос-платформа, але працюватиме під Linux.


1
Якщо ви збираєтесь дати рішення як команду оболонки, було б добре згадати систему (3)
dmckee --- кошеня колишнього модератора

26
#include <sys/types.h>
#include <sys/stat.h>

int status;
...
status = mkdir("/tmp/a/b/c", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

Від сюди . Можливо, вам доведеться робити окремі mkdirs для / tmp, / tmp / a, / tmp / a / b /, а потім / tmp / a / b / c, оскільки в C api немає еквівалента прапора -p. Будьте впевнені і ігноруйте EEXISTS errno, коли ви робите верхні рівні.


Факт забави: Принаймні Solaris та HP / UX мають mkdirp (), хоча це, очевидно, не оптимально для перенесення.
Мартін Карпентер

у цьому справа .. що я не хочу називати всі ці функції окремо.
Ліпіс

Виклик mkdir кілька разів буде набагато швидшим, ніж викликати систему один раз.
Пол Томблін

Я не розумію, що ви пропонуєте: дзвонити mkdir 4 рази різними аргументами? ("/tmp/",...), ("/tmp/a/",...), ("/tmp/a/b/",...),("/tmp/a/b/c/",...)
Антоніо

1
Знову ж таки, досить тривіально зробити той самий дзвінок тричі. Сенс у тому, щоб дати людям достатньо інформації, щоб вони могли написати код, а не писати код для них.
Пол Томблін

25

Ось мій приклад коду (він працює і для 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 ++ спосіб створення каталогу. Ця відповідь потребує більше результатів.
Мануель Лафонд

1
У Windows, isDirExist не працює, якщо символ символу є зворотним нахилом. Завжди повертає помилкове. Я повинен змінити код на: std :: string dirPath (path); while ('\\' == * dirPath.rbegin ()) dirPath.pop_back (); ... а потім, звичайно, передайте dirPath.c_str () у виклику до _stat.
MiloDC

API Windows має "Імена, які не є ANSI для сумісності" для stat(пов'язаного з __STDC__) відсутності потреби в тесті попереднього компілятора .
Сандберг

18

Слід зазначити, що інтерфейс файлової системи 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. Останнє потенційно не потребуватиме в майбутньому.


Також слід працювати з досить новими Visual C ++ та "/ std: c ++ найновішими". Дивіться: blogs.msdn.microsoft.com/vcblog/2018/05/07/… та developercommunity.visualstudio.com/content/problem/296680/…
Рон Берк

9

Це аналогічно попередньому, але працює вперед через рядок замість рекурсивно назад. Залишає errno з правильним значенням для останньої помилки. Якщо є провідна косої риски, є додатковий час через цикл, який можна було б уникнути за допомогою одного find_first_of () поза циклом або шляхом виявлення ведучого / та встановлення до 1. Ефективність однакова, якщо ми встановимо перший цикл або попередній цикл виклику, а складність буде (трохи) вищою при використанні виклику перед циклом.

#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';

}

7

Ви сказали "C ++", але всі, здається, думають про "Баш-шкаралупу".

Перевірте вихідний код на gnu mkdir; тоді ви можете побачити, як реалізувати команди оболонки в C ++.


Добре система ("mkdir ...") повинна зробити трюк на Linux. Хоча це не крос-платформа.
ChristopheD

Я другий, що говорить @MartinCarpenter
Джошуа Хеджес

6
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?
Rayee Roded

1
Знайдений відповідь, :: гарантує , що дозвіл походить від глобального простору імен stackoverflow.com/questions/4269034 / ...
Рейє Roded

4

Тому мені потрібно mkdirp()сьогодні, і знайшли рішення на цій сторінці надто складні. Отже, я написав досить короткий фрагмент, який легко скопіювати для інших, хто натрапляє на цю нитку, дивуючись, чому нам потрібно стільки рядків коду.

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.github.com/jonasfj/7797272
jonasfj

2
Зло намагатися змінити рядок, який передається як константа. Крім усього іншого, це, ймовірно, може призвести до драматичних збоїв, якщо він коли-небудь передається рядковим буквалом.
Джонатан Леффлер

2
Ідеально правильно .... це насправді погано ... напевно, strcpy зробив би це краще ...
jonasfj

3

Оскільки ця публікація займає високу позицію в Google за "Створення дерева каталогів", я збираюся опублікувати відповідь, яка буде працювати для Windows - це буде працювати за допомогою API Win32, зібраного для UNICODE або MBCS. Це переноситься з коду Марка вище.

Оскільки це система Windows, з якою ми працюємо, то роздільники каталогів є BACK-косою рискою, а не косою рисою вперед. Якщо ви хочете мати нахили вперед, змініть'\\' на'/'

Він буде працювати з:

c:\foo\bar\hello\world

і

c:\foo\bar\hellp\world\

(тобто: не потрібна косою косою рисою, тому не потрібно її перевіряти.)

Перш ніж сказати "Просто використовувати SHCreateDirectoryEx () в Windows", зауважте, що 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;
}

Один маленький мод - якщо шлях містить зворотні риски, це не працює. Тут: `LPCTSTR szLast = _tcsrchr (szPathTree, '\\');` Вам просто потрібно додати це: `` `if (nullptr == szLast) {szLast = _tcsrchr (szPathTree, '/'); } `` `
Ден-Джейсон

1
Дякуємо за інформацію. Що станеться, якщо шлях змішаний? тобто: c:\this\is\a/mixed/path\of\slashesКосої косої риски Windows - це зворотна косою рисою. Що повинно статися, це те, що абонент повинен саніфікувати шлях та забезпечити правильність всіх косої риски, перш ніж викликати цей метод.
Енді

3

Я знаю, що це старе питання, але він відображається високо в результатах пошуку 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, тому я вирішив пропустити її.


1

Якщо dir не існує, створіть його:

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

1

Тут описано дуже багато підходів, але для більшості з них потрібне жорстке кодування вашого шляху у ваш код. Існує просте рішення цієї проблеми з використанням 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());
}

Переконайтеся, що у вас є доступ для запису до цього Шляху.



0

Ось рекурсивна функція C / C ++, яка використовує dirname()для обходу дерева каталогіз знизу вгору. Він зупиниться, як тільки знайде наявного предка.

#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;
}

-2

Інші отримали правильну відповідь, але я подумав, що я продемонструю ще одне акуратне, що ви можете зробити:

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

Буде створено такі шляхи:

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

Дужки дозволяють створювати декілька каталогів одночасно на одному рівні ієрархії, тоді як -pопція означає "створити батьківські каталоги за потребою".


побачивши відповідь Павла, я розумію, що я (та багато інших людей) неправильно зрозуміли питання ...
rmeador

Якщо хтось може просто оновити це, перейшовши на систему ("mkdir -p / tmp / a / {b, c} / d"), викликайте питання не в тому, щоб це робити в оболонці .., а через C ++.
Ліпіс

Я думаю, що {a, b} буде працювати як в ш-похідних, так і в csh-оболонках. Я не впевнений, чи буде це працювати в команді system ().
Пол Томблін

1
@Lipis: робити це через system () - не вдале рішення питання ОП. @Andy: Я ніколи раніше не замислювався над цим, але я просто перевірив це, замінивши "mkdir -p" на "echo", і він виводить "/ tmp / a / b / d / tmp / a / c / d", що говорить про те, що це робить оболонка, а не mkdir.
rmeador

@rmeador: якщо це не вдале рішення, чи маєте щось ще запропонувати? Я хочу це зробити через C ++ ... це моє питання, а не як це зробити через оболонку ..
Ліпіс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.