Je veux un moyen simple de créer plusieurs répertoires en C ++ / Linux.
Par exemple, je souhaite enregistrer un fichier lola.file 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 de travail serait parfait.
Réponses:
Avec C ++ 17 ou version ultérieure, il y a l'en-tête standard
<filesystem>
avec une fonctionstd::filesystem::create_directories
qui devrait être utilisée dans les programmes C ++ modernes. Les fonctions standard C ++ n'ont cependant pas l'argument d'autorisations explicites (mode) spécifique à POSIX.Cependant, voici une fonction C qui peut être compilée avec des compilateurs C ++.
Les macros
STRDUP()
etFREE()
sont des versions de vérification des erreurs destrdup()
etfree()
, déclarées dansemalloc.h
(et implémentées dansemalloc.c
etestrdup.c
). L'en-"sysstat.h"
tête traite des versions cassées de<sys/stat.h>
et peut être remplacé par<sys/stat.h>
sur les systèmes Unix modernes (mais il y avait de nombreux problèmes en 1990). Et"mkpath.h"
déclaremkpath()
.Le changement entre v1.12 (version originale de la réponse) et v1.13 (version modifiée de la réponse) était le test pour
EEXIST
dansdo_mkdir()
. Cela a été signalé comme nécessaire par Switch - merci, Switch. Le code de test a été mis à jour et reproduit le problème sur un MacBook Pro (Intel Core i7 2,3 GHz, exécutant Mac OS X 10.7.4), et suggère que le problème est résolu dans la révision (mais les tests ne peuvent montrer que la présence de bogues , jamais leur absence). Le code affiché est maintenant v1.16; des modifications cosmétiques ou administratives ont été apportées depuis la v1.13 (comme l'utilisation à lamkpath.h
place dejlss.h
et l'inclusion<unistd.h>
inconditionnelle dans le code de test uniquement). Il est raisonnable de dire que cela"sysstat.h"
devrait être remplacé par à<sys/stat.h>
moins que vous n'ayez un système inhabituellement récalcitrant.(Vous êtes autorisé par la présente à utiliser ce code à toute fin avec attribution.)
Ce code est disponible dans mon référentiel SOQ (Stack Overflow Questions) sur GitHub sous forme de fichiers
mkpath.c
etmkpath.h
(etc.) dans le sous-répertoire src / so-0067-5039 .la source
if (errno != EEXIST) { status = -1; }
lorsque mkdir échoue.stat()
avantmkdir()
; il s'agit d'un problème TOCTOU (heure de contrôle, heure d'utilisation). J'ai essayé de chatouiller le bogue avec un script shell exécutant 13 processus en arrière-plan créant le même chemin de 29 éléments, et je n'ai pas réussi à le frapper. Ensuite, j'ai piraté le programme de test pour le fork 20 fois et j'ai demandé à chaque enfant d'essayer, et cela a réussi à toucher le bogue. Le code fixe auraif (mkdir(path, mode) != 0 && errno != EEXIST) status = -1;
. Cela ne montre pas le bogue.jlss.h
,emalloc.h
), pas des bibliothèques. Cependant, le code est disponible dans mon référentiel SOQ (Stack Overflow Questions) sur GitHub sous forme de fichiersjlss.h
,emalloc.c
etemalloc.h
dans le sous-répertoire src / libsoq . Vous aurez besoinposixver.h
aussi, et quelques autres (debug.h
,stderr.c
,stderr.h
- je pense que ce, mais ce que vous avez besoin devraient tous être dans ce répertoire).Facile avec Boost.Filesystem:
create_directories
Retourne:
true
si un nouveau répertoire a été créé, sinonfalse
.la source
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.
est le moyen le plus court auquel je puisse penser (en termes de longueur de code, pas nécessairement de temps d'exécution).
Ce n'est pas multiplateforme mais fonctionnera sous Linux.
la source
D' ici . Vous devrez peut-être faire des mkdirs séparés pour / tmp, / tmp / a, / tmp / a / b / et ensuite / tmp / a / b / c car il n'y a pas d'équivalent de l'indicateur -p dans l'API C. Soyez sûr et ignorez l'erreur EEXISTS pendant que vous faites les niveaux supérieurs.
la source
("/tmp/",...)
,("/tmp/a/",...)
,("/tmp/a/b/",...)
,("/tmp/a/b/c/",...)
Voici mon exemple de code (cela fonctionne à la fois pour Windows et Linux):
Usage:
la source
stat
(liés à__STDC__
) aucun besoin de test de précompilateur.Il est à noter qu'à partir de l'interface du système de fichiers C ++ 17 fait partie de la bibliothèque standard. Cela signifie que l'on peut avoir les éléments suivants pour créer des répertoires:
Plus d'informations ici: https://en.cppreference.com/w/cpp/filesystem/create_directory
De plus, avec gcc, il faut "-std = c ++ 17" vers CFLAGS. Et "-lstdc ++ fs" vers LDLIBS. Ce dernier ne sera potentiellement pas nécessaire à l'avenir.
la source
Ceci est similaire au précédent mais fonctionne en avant à travers la chaîne au lieu de recursivement en arrière. Laisse errno avec la bonne valeur pour le dernier échec. S'il y a une barre oblique au début, il y a un temps supplémentaire dans la boucle qui aurait pu être évité via un find_first_of () en dehors de la boucle ou en détectant le premier / et en mettant pre à 1. L'efficacité est la même que nous soyons configurés par un première boucle ou un appel de pré-boucle, et la complexité serait (légèrement) plus élevée lors de l'utilisation de l'appel de pré-boucle.
la source
Vous avez dit «C ++», mais tout le monde ici semble penser «shell Bash».
Consultez le code source de gnu
mkdir
; alors vous pouvez voir comment implémenter les commandes shell en C ++.la source
la source
J'ai donc besoin
mkdirp()
aujourd'hui, et trouve les solutions sur cette page trop compliquées. Par conséquent, j'ai écrit un extrait assez court, qui peut facilement être copié pour ceux qui tombent sur ce fil de discussion et se demandent pourquoi nous avons besoin de tant de lignes de code.mkdirp.h
mkdirp.cpp
Si vous n'aimez pas le cast const et la modification temporaire de la chaîne, faites simplement un
strdup()
etfree()
après.la source
Étant donné que cet article est bien classé dans Google pour "Créer une arborescence de répertoires", je vais publier une réponse qui fonctionnera pour Windows - cela fonctionnera en utilisant l'API Win32 compilée pour UNICODE ou MBCS. Ceci est porté à partir du code de Mark ci-dessus.
Puisqu'il s'agit de Windows avec lequel nous travaillons, les séparateurs de répertoire sont des barres obliques ARRIÈRE, pas des barres obliques. Si vous préférez avoir des barres obliques, passez
'\\'
à'/'
Cela fonctionnera avec:
et
(c'est-à-dire: n'a pas besoin de barre oblique de fin, vous n'avez donc pas à le vérifier.)
Avant de dire «Utilisez simplement SHCreateDirectoryEx () sous Windows», notez que SHCreateDirectoryEx () est obsolète et pourrait être supprimé à tout moment des futures versions de Windows.
la source
c:\this\is\a/mixed/path\of\slashes
barres obliques Windows sont généralement des barres obliques inverses. Ce qui devrait se passer, c'est que l'appelant doit nettoyer le chemin et s'assurer que toutes les barres obliques sont correctes avant d'appeler cette méthode.Je sais que c'est une vieille question, mais elle apparaît en bonne place dans les résultats de recherche Google et les réponses fournies ici ne sont pas vraiment en C ++ ou sont un peu trop compliquées.
Veuillez noter que dans mon exemple, createDirTree () est très simple car tout le travail lourd (vérification des erreurs, validation de chemin) doit être fait de toute façon par createDir (). De plus, createDir () devrait retourner true si le répertoire existe déjà ou si tout ne fonctionnera pas.
Voici comment je ferais cela en C ++:
Bien sûr, la fonction createDir () sera spécifique au système et il y a déjà suffisamment d'exemples dans d'autres réponses pour l'écrire pour Linux, j'ai donc décidé de l'ignorer.
la source
Si dir n'existe pas, créez-le:
la source
De nombreuses approches ont été décrites ici, mais la plupart d'entre elles nécessitent un codage en dur de votre chemin dans votre code. Il existe une solution simple à ce problème, en utilisant QDir et QFileInfo, deux classes du framework Qt. Étant donné que vous êtes déjà dans un environnement Linux, il devrait être facile d'utiliser Qt.
Assurez-vous que vous disposez d'un accès en écriture à ce chemin.
la source
la source
-p
option est ce que je recherche. Merci!Voici la fonction récursive C / C ++ qui utilise
dirname()
pour parcourir de bas en haut l'arborescence de répertoires. Il s'arrêtera dès qu'il trouvera un ancêtre existant.la source
Les autres vous ont donné la bonne réponse, mais j'ai pensé vous montrer une autre chose intéressante que vous pouvez faire:
Créera les chemins suivants:
Les accolades vous permettent de créer plusieurs répertoires à la fois au même niveau de la hiérarchie, alors que l'
-p
option signifie «créer des répertoires parents selon les besoins».la source