C ++ не имеет встроенных средств для создания каталогов и деревьев как таковых . Вам придется использовать C и системные вызовы или внешнюю библиотеку, такую как Boost. C и системные вызовы будут зависеть от платформы.
jww
6
@noloader Большое спасибо, чувак ... но я думаю, что через 4 года я в значительной степени получил свой ответ, как вы можете видеть ниже 13 различными способами ...
Липис
Да, я был удивлен, что никто прямо не заявил, что вы не можете сделать это на C ++ (при условии, что вам нужен переносимый метод на C ++, работающий в Linux). Но вы, наверное, знали об этом;). Однако было много хороших предложений для непереносимого кода C.
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"typedefstruct stat Stat;staticint do_mkdir(constchar*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;}elseif(!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(constchar*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 (исправленная версия ответа) была проверкой для EEXISTin
do_mkdir(). Switch указала на это как на необходимость
- спасибо, Switch. Код теста был обновлен и воспроизводит проблему на MacBook Pro (Intel Core i7 2,3 ГГц, под управлением Mac OS X 10.7.4) и предполагает, что проблема исправлена в версии (но тестирование может показать только наличие ошибок , никогда их отсутствие). Показанный код теперь v1.16; начиная с версии 1.13 были внесены косметические или административные изменения (такие как использование mkpath.hвместо jlss.hи <unistd.h>безоговорочное включение только в тестовый код). Разумно утверждать, что его "sysstat.h"следует заменить на,
<sys/stat.h>если только у вас нет необычно стойкой системы.
(Настоящим вам дается разрешение использовать этот код в любых целях с указанием авторства.)
Это наверняка быстрее системы. Система имеет много накладных расходов. По сути, процесс должен быть разветвлен, затем должны быть загружены как минимум два двоичных файла (один, вероятно, уже будет в кеше), один из которых будет еще одним форком другого, ...
ypnos
1
Я забыл: и тогда "mkdir -p" будет делать, по крайней мере, то же самое, что и указанный выше код!
ypnos
7
В этом коде есть тонкое состояние гонки, которое я действительно затронул. Это происходит только тогда, когда несколько программ запускаются одновременно и используют один и тот же путь к папке. Исправление - добавить, if (errno != EEXIST) { status = -1; }когда mkdir не работает.
Switch
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- я думаю , что это, но то , что вам нужно все должны быть в этом каталоге).
Что ж, большинство буст-библиотек предназначены только для заголовков, что означает отсутствие дополнительных затрат, кроме того, что вы используете. В случае с Boost.Filesystem он требует компиляции. На моем диске скомпилированная библиотека весит ~ 60КБ.
Benoît
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.
ИМХО: В любом моем проекте, который призван сделать что-то значимое и выдержать испытание временем, ХОРОШО стоит компиляция иметь такой набор невероятно полезных и мощных стандартизированных инструментов, как boost. Многие из них уже вошли в стандартный C ++, и, конечно же, в будущем. Попробуйте, придерживайтесь этого, вы выиграете, если у вас будут более чем тривиальные потребности, и вы не хотите изобретать велосипед. :-)
moodboom
42
system("mkdir -p /tmp/a/b/c")
это самый короткий способ, о котором я могу думать (с точки зрения длины кода, не обязательно времени выполнения).
Он не кроссплатформенный, но будет работать под Linux.
От сюда . Возможно, вам придется сделать отдельные mkdirs для / tmp, / tmp / a, / tmp / a / b /, а затем / tmp / a / b / c, потому что в C api нет эквивалента флага -p. Будьте уверены и игнорируйте ошибку EEXISTS при выполнении операций верхнего уровня.
Интересный факт: по крайней мере, в Solaris и HP / UX есть mkdirp (), хотя это явно не оптимально для переносимости.
Мартин Карпентер,
в том-то и дело .. что я не хочу вызывать все эти функции по отдельности.
Lipis
Вызов mkdir несколько раз будет намного быстрее, чем вызов системы один раз.
Пол Томблин,
Я не понимаю, что вы предлагаете: вызвать mkdir 4 раза с разными аргументами? ("/tmp/",...), ("/tmp/a/",...), ("/tmp/a/b/",...),("/tmp/a/b/c/",...)
Антонио
1
Опять же, довольно просто сделать один и тот же вызов три раза. Дело в том, чтобы дать людям достаточно информации, чтобы они могли писать код, а не писать код за них.
Пол Томблин
25
Вот мой пример кода (работает как для Windows, так и для Linux):
Я поддерживаю этот комментарий! Это (на удивление) нетривиальная задача найти переносимый C ++ способ создания каталога. Этот ответ требует больше голосов.
Мануэль Лафонд
1
В Windows isDirExist не работает, если конечный символ - обратная косая черта. Всегда возвращает false. Мне нужно изменить код на: std :: string dirPath (path); while ('\\' == * dirPath.rbegin ()) dirPath.pop_back (); ... а затем, конечно, передайте dirPath.c_str () в вызове _stat.
MiloDC
Windows API имеет «имена Non-ANSI для совместимости» для stat(связанные с __STDC__) нет необходимости в тесте прекомпилятора.
Сандберг
18
Следует отметить, что начиная с C ++ 17 интерфейс файловой системы является частью стандартной библиотеки. Это означает, что для создания каталогов можно использовать:
Это похоже на предыдущее, но работает вперед по строке, а не рекурсивно назад. Оставляет в errno правильное значение для последней ошибки. Если есть начальная косая черта, то в цикле есть дополнительное время, которого можно было бы избежать с помощью одной find_first_of () вне цикла или путем обнаружения ведущего / и установки pre равным 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 lengthif((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';}
Итак, мне нужно 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(constchar* path,mode_t mode = DEFAULT_MODE);#endif// MKDIRP_H
mkdirp.cpp
#include<errno.h>bool mkdirp(constchar* path,mode_t mode){// const cast for hackchar* p =const_cast<char*>(path);// Do mkdir for each slash until end of string or errorwhile(*p !='\0'){// Skip first character
p++;// Find first slash or endwhile(*p !='\0'&&*p !='/') p++;// Remember value from pchar v =*p;// Write end of string at p*p ='\0';// Create folder from path to '\0' inserted at pif(mkdir(path, mode)==-1&& errno != EEXIST){*p = v;returnfalse;}// Restore path to it's former glory*p = v;}returntrue;}
Если вам не нравится приведение констант и временное изменение строки, просто выполните a, strdup()а free()затем.
Добавлено в суть, так что я не забываю, где я положу его в следующий раз, когда он понадобится :) gist.github.com/jonasfj/7797272
jonasfj
2
Плохо пытаться изменить строку, которая передается как константа. Помимо прочего, это может привести к серьезным сбоям, если ему когда-либо будет передан строковый литерал.
Джонатан Леффлер,
2
Совершенно верно .... это на самом деле плохо ... вероятно, strcpy сделает это лучше ...
jonasfj
3
Поскольку этот пост занимает высокое место в Google по «Создать дерево каталогов», я собираюсь опубликовать ответ, который будет работать для Windows - это будет работать с использованием Win32 API, скомпилированного для UNICODE или MBCS. Это перенесено из кода Марка выше.
Так как мы работаем с Windows, разделителями каталогов являются обратная косая черта, а не косая черта. Если вы предпочитаете косую черту, измените ее '\\'на'/'
Он будет работать с:
c:\foo\bar\hello\world
и
c:\foo\bar\hellp\world\
(например: не требуется завершающая косая черта, поэтому вам не нужно ее проверять.)
Прежде чем сказать «Просто используйте SHCreateDirectoryEx () в Windows», обратите внимание, что SHCreateDirectoryEx () устарела и может быть удалена в любое время из будущих версий Windows.
Одна маленькая модификация - если путь содержит обратную косую черту, это не сработает. Здесь: `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;returntrue;}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");return0;}
Конечно, функция createDir () будет зависеть от системы, и в других ответах уже есть достаточно примеров, как ее написать для Linux, поэтому я решил ее пропустить.
Здесь было описано так много подходов, но большинство из них требует жесткого кодирования вашего пути в ваш код. Есть простое решение этой проблемы, используя 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());}
Убедитесь, что у вас есть доступ на запись к этому пути.
Вот рекурсивная функция C / C ++, которая использует dirname()для просмотра дерева каталогов снизу вверх. Он остановится, как только найдет существующего предка.
#include<libgen.h>#include<string.h>int create_dir_tree_recursive(constchar*path,constmode_t mode){if(strcmp(path,"/")==0)// No need of checking if we are at root.return0;// 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;}return0;}
Другие дали вам правильный ответ, но я подумал, что продемонстрирую еще одну интересную вещь, которую вы можете сделать:
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 ++.
Lipis
Я думаю, что {a, b} будет работать как в оболочках, производных от sh, так и от csh. Однако я не уверен, будет ли он работать в команде system ().
Пол Томблин,
1
@Lipis: выполнение этого через system () не является хорошим решением вопроса OP. @Andy: Я никогда не думал об этом раньше, но я просто протестировал это, заменив "mkdir -p" на "echo", и он распечатает "/ tmp / a / b / d / tmp / a / c / d", что предполагает, что это делает оболочка, а не mkdir.
rmeador
@rmeador: если это не лучшее решение, у вас есть что предложить? Я хочу сделать это через C ++ ... моя проблема не в том, как это сделать через оболочку ...
Ответы:
В C ++ 17 и новее есть стандартный заголовок
<filesystem>
с функцией,std::filesystem::create_directories
который следует использовать в современных программах на C ++. Однако стандартные функции C ++ не имеют специфичного для POSIX аргумента явных разрешений (режима).Однако вот функция C, которую можно скомпилировать с помощью компиляторов C ++.
Макросы
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
indo_mkdir()
. Switch указала на это как на необходимость - спасибо, Switch. Код теста был обновлен и воспроизводит проблему на MacBook Pro (Intel Core i7 2,3 ГГц, под управлением Mac OS X 10.7.4) и предполагает, что проблема исправлена в версии (но тестирование может показать только наличие ошибок , никогда их отсутствие). Показанный код теперь v1.16; начиная с версии 1.13 были внесены косметические или административные изменения (такие как использованиеmkpath.h
вместоjlss.h
и<unistd.h>
безоговорочное включение только в тестовый код). Разумно утверждать, что его"sysstat.h"
следует заменить на,<sys/stat.h>
если только у вас нет необычно стойкой системы.(Настоящим вам дается разрешение использовать этот код в любых целях с указанием авторства.)
Этот код доступен в моем репозитории SOQ (Stack Overflow Questions) на GitHub в виде файлов
mkpath.c
иmkpath.h
(и т.д.) в подкаталоге src / so-0067-5039 .источник
if (errno != EEXIST) { status = -1; }
когда mkdir не работает.stat()
раньшеmkdir()
; это проблема TOCTOU (время проверки, время использования). Я попытался устранить ошибку с помощью сценария оболочки, запускающего 13 процессов в фоновом режиме, создавая тот же путь из 29 элементов, и мне не удалось его обработать. Затем я взломал тестовую программу на форк 20 раз и попросил каждого ребенка попробовать, и это помогло устранить ошибку. Фиксированный код будет иметьif (mkdir(path, mode) != 0 && errno != EEXIST) status = -1;
. Это не показывает ошибку.jlss.h
,emalloc.h
), а не библиотеки. Тем не менее, код доступен в моем SOQ (переполнению стека Вопросы) репозиторий на GitHub в виде файловjlss.h
,emalloc.c
иemalloc.h
в SRC / libsoq подкаталоге. Вам нужноposixver.h
также, и несколько других (debug.h
,stderr.c
,stderr.h
- я думаю , что это, но то , что вам нужно все должны быть в этом каталоге).Легко с Boost.Filesystem:
create_directories
Возвращает:
true
если был создан новый каталог, в противном случаеfalse
.источник
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.
это самый короткий способ, о котором я могу думать (с точки зрения длины кода, не обязательно времени выполнения).
Он не кроссплатформенный, но будет работать под Linux.
источник
От сюда . Возможно, вам придется сделать отдельные mkdirs для / tmp, / tmp / a, / tmp / a / b /, а затем / tmp / a / b / c, потому что в C api нет эквивалента флага -p. Будьте уверены и игнорируйте ошибку EEXISTS при выполнении операций верхнего уровня.
источник
("/tmp/",...)
,("/tmp/a/",...)
,("/tmp/a/b/",...)
,("/tmp/a/b/c/",...)
Вот мой пример кода (работает как для Windows, так и для Linux):
Использование:
источник
stat
(связанные с__STDC__
) нет необходимости в тесте прекомпилятора.Следует отметить, что начиная с C ++ 17 интерфейс файловой системы является частью стандартной библиотеки. Это означает, что для создания каталогов можно использовать:
Подробнее здесь: https://en.cppreference.com/w/cpp/filesystem/create_directory
Кроме того, с gcc нужно "-std = c ++ 17" для CFLAGS. И "-lstdc ++ fs" для LDLIBS. Последнее потенциально не понадобится в будущем.
источник
Это похоже на предыдущее, но работает вперед по строке, а не рекурсивно назад. Оставляет в errno правильное значение для последней ошибки. Если есть начальная косая черта, то в цикле есть дополнительное время, которого можно было бы избежать с помощью одной find_first_of () вне цикла или путем обнаружения ведущего / и установки pre равным 1. Эффективность такая же, независимо от того, настроены ли мы с помощью первый цикл или вызов предварительного цикла, и сложность будет (немного) выше при использовании вызова предварительного цикла.
источник
Вы сказали «C ++», но, похоже, все здесь думают «оболочка Bash».
Ознакомьтесь с исходным кодом GNU
mkdir
; тогда вы увидите, как реализовать команды оболочки на C ++.источник
источник
Итак, мне нужно
mkdirp()
сегодня, и я нашел решения на этой странице слишком сложными. Поэтому я написал довольно короткий фрагмент, который легко скопировать для других, кто наткнется на эту тему и задастся вопросом, зачем нам нужно так много строк кода.mkdirp.h
mkdirp.cpp
Если вам не нравится приведение констант и временное изменение строки, просто выполните a,
strdup()
аfree()
затем.источник
Поскольку этот пост занимает высокое место в Google по «Создать дерево каталогов», я собираюсь опубликовать ответ, который будет работать для Windows - это будет работать с использованием Win32 API, скомпилированного для UNICODE или MBCS. Это перенесено из кода Марка выше.
Так как мы работаем с Windows, разделителями каталогов являются обратная косая черта, а не косая черта. Если вы предпочитаете косую черту, измените ее
'\\'
на'/'
Он будет работать с:
и
(например: не требуется завершающая косая черта, поэтому вам не нужно ее проверять.)
Прежде чем сказать «Просто используйте SHCreateDirectoryEx () в Windows», обратите внимание, что SHCreateDirectoryEx () устарела и может быть удалена в любое время из будущих версий Windows.
источник
c:\this\is\a/mixed/path\of\slashes
Обычно косая черта Windows является обратной. Что должно произойти, так это то, что вызывающий должен очистить путь и убедиться, что все косые черты правильны, прежде чем вызывать этот метод.Я знаю, что это старый вопрос, но он часто появляется в результатах поиска Google, а приведенные здесь ответы на самом деле не на C ++ или слишком сложны.
Обратите внимание, что в моем примере createDirTree () очень прост, потому что вся тяжелая работа (проверка ошибок, проверка пути) в любом случае должна выполняться createDir (). Также createDir () должен возвращать true, если каталог уже существует, иначе все не будет работать.
Вот как я бы сделал это на C ++:
Конечно, функция createDir () будет зависеть от системы, и в других ответах уже есть достаточно примеров, как ее написать для Linux, поэтому я решил ее пропустить.
источник
Если каталог не существует, создайте его:
источник
Здесь было описано так много подходов, но большинство из них требует жесткого кодирования вашего пути в ваш код. Есть простое решение этой проблемы, используя QDir и QFileInfo, два класса фреймворка Qt. Поскольку вы уже находитесь в среде Linux, вам должно быть легко использовать Qt.
Убедитесь, что у вас есть доступ на запись к этому пути.
источник
источник
-p
вариант это то , что я ищу. Спасибо!Вот рекурсивная функция C / C ++, которая использует
dirname()
для просмотра дерева каталогов снизу вверх. Он остановится, как только найдет существующего предка.источник
Другие дали вам правильный ответ, но я подумал, что продемонстрирую еще одну интересную вещь, которую вы можете сделать:
Создадим следующие пути:
Фигурные скобки позволяют вам создавать несколько каталогов одновременно на одном уровне иерархии, тогда как
-p
опция означает «создавать родительские каталоги по мере необходимости».источник