Comment puis-je créer un répertoire de l'arborescence en C++/Linux?
Je veux un moyen facile de créer plusieurs répertoires en C++/Linux.
Par exemple je veux enregistrer un fichier de lola.fichier dans le répertoire:
/tmp/a/b/c
mais si les répertoires ne sont pas là, je veux qu'ils soient créés automatiquement. Un exemple serait parfait.
- C++ n'a pas de fonction intégrée pour la création des répertoires et des arbres en soi. Vous devrez utiliser le C et le système des appels ou d'une bibliothèque externe comme Boost. C et système d'appels seront dépendants de la plateforme.
- Merci beaucoup de l'homme.. mais je pense qu'après 4 ans j'ai eu ma réponse comme vous pouvez le voir ci-dessous dans 13 façons différentes...
- Ouais, j'ai été surpris pas explicitement dit que vous ne pouvez pas le faire en C++ (en supposant que vous voulais un portable méthode en C++, qui a travaillé sur Linux). Mais vous savait probablement que ça ;). Il y avait beaucoup de bonnes suggestions pour les non-C portable code.
- Qu'est-ce que "C++/Linux"?
- C'est mes années d'université en C++ sur Linux 🙂
Vous devez vous connecter pour publier un commentaire.
Voici une fonction C qui peut être compilé avec les compilateurs C++.
Les macros
STRDUP()
etFREE()
sont d'erreur de vérification des versions destrdup()
etfree()
, a déclaré dansemalloc.h
(et mis en œuvre dansemalloc.c
etestrdup.c
). Le"sysstat.h"
en-tête de traite cassé versions de<sys/stat.h>
et peut être remplacé par<sys/stat.h>
sur les systèmes Unix modernes (mais il y avait beaucoup de questions en 1990). Et"jlss.h"
déclaremkpath()
.Le changement entre les v1.12 (précédent) et v1.13 (ci-dessus) est le test de la
EEXIST
dansdo_mkdir()
. Cela a été souligné que de besoin, par Commutateur — merci à vous, passez. Le code de test a été mis à niveau et de reproduire le problème sur un MacBook Pro (2,3 GHz Intel Core i7, fonctionnant sous Mac OS X 10.7.4), et suggère que le problème est corrigé dans la révision (mais les tests ne peuvent montrer la présence de bugs, de ne jamais leur absence).(Vous êtes par les présentes donné la permission d'utiliser ce code pour n'importe quel but avec mention de la source.)
if (errno != EEXIST) { status = -1; }
quand mkdir échoue.stat()
avantmkdir()
; c'est un TOCTOU (le temps de vérifier, au moment de l'utilisation) problème. J'ai essayé de chatouiller le bug avec un script shell en cours d'exécution 13 processus en arrière-plan de la création de la même 29-chemin d'élément, et n'ai pas réussi à le frapper. Ensuite, j'ai piraté le programme de test de la fourche à la fourchette, 20 fois, et demandez à chaque enfant d'essayer, et qui a réussi à frapper le bug. Le code fixe auraif (mkdir(path, mode) != 0 && errno != EEXIST) status = -1;
. Qui ne montre pas le bug.jlss.h
,emalloc.h
), pas de bibliothèques. Toutefois, le code est disponible dans mon OSQ (Débordement de Pile Questions) dépôt sur GitHub que les fichiersjlss.h
,emalloc.c
etemalloc.h
dans le src/libsoq sous-répertoire. Vous aurez besoinposixver.h
trop, et quelques autres (debug.h
,stderr.c
,stderr.h
— je pense que c'est ça, mais ce que vous devez doivent tous être dans ce répertoire).Facile avec Boost.Système de fichiers:
create_directories
Retourne:
true
si un nouveau répertoire a été créé, sinonfalse
.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.
fs::create_directories
maintenant!est le chemin le plus court je pense (en termes de longueur de code, pas nécessairement le temps d'exécution).
Il n'est pas multi-plateforme, mais fonctionnera sous Linux.
Voici mon exemple de code (il fonctionne aussi bien sur Windows et Linux):
Utilisation:
stat
(liées à__STDC__
) pas besoin de le précompilateur test.De ici. Vous pourriez avoir à faire des mkdirs pour /tmp, /tmp,/a, /tmp/a/b/et puis /tmp/a/b/c parce que il n'y a pas un équivalent de l'option-p au C de l'api. Assurez-vous et d'ignorer les EEXISTS errno pendant que vous êtes en train de faire du haut niveau.
("/tmp/",...)
,("/tmp/a/",...)
,("/tmp/a/b/",...)
,("/tmp/a/b/c/",...)
mkdir
sont beaucoup plus efficace que d'appelersystem
une fois. Toutefois, si vous avez à faire la/tmp
répertoire, vous avez de plus gros problèmes que je peux vous aider avec.create_directories
de prendre le chemin d'entrée, il faudrait préliminaire fendre le chemin d'entrée. Dans cette solution, c'est juste une question de concaténer 2 chaînes pour créer le système de commande d'appel.mkdir
que j'ai mentionné dans mon commentaire précédent.Ceci est similaire à la précédente mais les œuvres de l'avant par le biais de la chaîne, au lieu de récursivement en arrière. Les feuilles errno avec la valeur du dernier échec. Si il y a un slash, il y a un temps supplémentaire à travers la boucle qui aurait pu être évitée par un find_first_of() en dehors de la boucle ou par la détection de la tête /et réglage du pré à 1. L'efficacité est la même, que l'on s'installe par une première boucle ou un pré boucle d'appel, et de la complexité serait (un peu) plus élevé lors de l'utilisation de la pré-boucle d'appel.
Il convient de noter qu'à partir de C++17 système de fichiers de l'interface est la partie de la bibliothèque standard. Cela signifie que l'on peut avoir à la suite de la création de répertoires:
Plus d'infos ici: https://en.cppreference.com/w/cpp/filesystem/create_directory
En outre, avec gcc, il faut "-std=c++17" à CFLAGS. Et "-lstdc++fs" pour LDLIBS. Le dernier potentiellement ne va pas être nécessaire dans le futur.
Vous avez dit "C++", mais tout le monde ici semble être en train de penser "shell Bash."
Vérifier le code source de gnu
mkdir
; ensuite, vous pouvez voir comment mettre en œuvre les commandes shell en C++.Je sais que c'est une vieille question, mais il montre en haut sur les résultats de recherche google et les réponses fournies ici ne sont pas vraiment en C++ ou en sont un peu trop compliqué.
Veuillez noter que dans mon exemple createDirTree() est très simple, parce que tout le levage lourd (erreur de vérification, de validation du chemin d'accès) doit être fait par createDir() de toute façon. Aussi createDir() doit retourner true si le répertoire existe déjà ou toute chose ne fonctionne pas.
Voici comment je pourrais le faire en C++:
Bien sûr createDir() va être spécifiques au système et il y a déjà suffisamment d'exemples dans d'autres réponses sur la façon de l'écrire pour linux, j'ai donc décidé de l'ignorer.
J'ai donc besoin d'
mkdirp()
aujourd'hui, et a trouvé des solutions sur cette page, trop compliqué.Donc j'ai écrit un assez court extrait, qui facilement être copié pour les autres qui
tomber sur ce fil un demander pourquoi nous avons besoin d'autant de lignes de code.
mkdirp.h
mkdirp.cpp
Si vous n'aimez pas const casting et en modifiant temporairement la chaîne, il suffit de faire une
strdup()
etfree()
par la suite.Depuis ce post est de rang élevé dans Google pour "Créer une Arborescence de Répertoire", je vais poster une réponse qui fonctionne pour Windows — ce qui fonctionne à l'aide de l'API Win32 compilé pour UNICODE ou MBCS. Ce est porté à partir de la Marque de code ci-dessus.
Puisque c'est Windows qui travaillent avec nous, répertoire des séparateurs sont des anti-slash, pas de barres obliques. Si vous préférez des barres obliques, changement
'\\'
à'/'
Il travaillera avec:
et
(c'est à dire: n'a pas besoin de slash de fin, de sorte que vous n'avez pas à les vérifier.)
Avant de dire "il suffit d'utiliser SHCreateDirectoryEx() dans Windows", note que SHCreateDirectoryEx() est obsolète et pourrait être retiré à tout moment à partir de futures versions de Windows.
Si dir n'existe pas, la créer:
-p
option est ce que je suis à la recherche pour. Merci!Les autres vous avez le droit de réponse, mais j'ai pensé que je voudrais vous montrer une autre chose que vous pouvez faire:
Permettra de créer des chemins d'accès suivants:
Les accolades permettent de créer plusieurs répertoires à la fois sur le même niveau de la hiérarchie, alors que la
-p
option "créer les répertoires parents en tant que de besoin".dash
etc) ne prennent pas en charge accolade de l'expansion.