Ich möchte eine einfache Möglichkeit, mehrere Verzeichnisse in C ++ / Linux zu erstellen.
Zum Beispiel möchte ich eine Datei lola.file im Verzeichnis speichern:
/tmp/a/b/c
aber wenn die Verzeichnisse nicht da sind, möchte ich, dass sie automatisch erstellt werden. Ein funktionierendes Beispiel wäre perfekt.
Antworten:
Ab C ++ 17 gibt es den Standardheader
<filesystem>
mit Funktionstd::filesystem::create_directories
, der in modernen C ++ - Programmen verwendet werden sollte. Die C ++ - Standardfunktionen verfügen jedoch nicht über das POSIX-spezifische Argument für explizite Berechtigungen (Modus).Hier ist jedoch eine C-Funktion, die mit C ++ - Compilern kompiliert werden kann.
Die Makros
STRDUP()
undFREE()
sind fehlerprüfende Versionen vonstrdup()
undfree()
, deklariert inemalloc.h
(und implementiert inemalloc.c
undestrdup.c
). Der"sysstat.h"
Header befasst sich mit defekten Versionen von<sys/stat.h>
und kann durch<sys/stat.h>
moderne Unix-Systeme ersetzt werden (aber es gab bereits 1990 viele Probleme). Und"mkpath.h"
erklärtmkpath()
.Der Wechsel zwischen v1.12 (Originalversion der Antwort) und v1.13 (geänderte Version der Antwort) war der Test für
EEXIST
indo_mkdir()
. Dies wurde von Switch als notwendig herausgestellt - danke, Switch. Der Testcode wurde aktualisiert und das Problem auf einem MacBook Pro (2,3 GHz Intel Core i7 unter Mac OS X 10.7.4) reproduziert. Er weist darauf hin, dass das Problem in der Revision behoben wurde (Tests können jedoch nur das Vorhandensein von Fehlern anzeigen niemals ihre Abwesenheit). Der angezeigte Code ist jetzt v1.16; Seit Version 1.13 wurden kosmetische oder administrative Änderungen vorgenommen (z. B. Verwendungmkpath.h
anstelle vonjlss.h
und<unistd.h>
bedingungslos nur im Testcode enthalten ). Es ist vernünftig zu argumentieren, dass"sysstat.h"
dies durch ersetzt werden sollte, es<sys/stat.h>
sei denn, Sie haben ein ungewöhnlich widerspenstiges System.(Sie erhalten hiermit die Erlaubnis, diesen Code für jeden Zweck mit Namensnennung zu verwenden.)
Dieser Code ist in meinem SOQ- Repository (Stack Overflow Questions) auf GitHub als Dateien
mkpath.c
undmkpath.h
(usw.) im Unterverzeichnis src / so-0067-5039 verfügbar .quelle
if (errno != EEXIST) { status = -1; }
Update muss hinzugefügt werden, wenn mkdir fehlschlägt.stat()
vormkdir()
; Es handelt sich um ein TOCTOU-Problem (Prüfzeitpunkt, Verwendungszeitpunkt). Ich habe versucht, den Fehler mit einem Shell-Skript zu kitzeln, das 13 Prozesse im Hintergrund ausführt und denselben Pfad mit 29 Elementen erstellt, und es nicht geschafft, ihn zu treffen. Dann habe ich das Testprogramm 20 Mal gehackt, um es zu gabeln und jedes Kind versuchen zu lassen, und das hat es geschafft, den Fehler zu treffen. Der feste Code wird habenif (mkdir(path, mode) != 0 && errno != EEXIST) status = -1;
. Das zeigt den Fehler nicht.jlss.h
,emalloc.h
), keine Bibliotheken. Allerdings ist der Code in meinen verfügbar SOQ (Stack Overflow Questions) Repository auf GitHub als Dateienjlss.h
,emalloc.c
undemalloc.h
im src / libsoq Unterverzeichnis. Sie müssenposixver.h
auch, und ein paar andere (debug.h
,stderr.c
,stderr.h
- ich glaube , das ist es, aber was Sie brauchen , um alle in diesem Verzeichnis sein sollte).Einfach mit Boost.Filesystem:
create_directories
Rückgabe:
true
Wenn andernfalls ein neues Verzeichnis erstellt wurdefalse
.quelle
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.
ist der kürzeste Weg, den ich mir vorstellen kann (in Bezug auf die Länge des Codes, nicht unbedingt die Ausführungszeit).
Es ist nicht plattformübergreifend, funktioniert aber unter Linux.
quelle
Von hier aus . Möglicherweise müssen Sie separate mkdirs für / tmp, / tmp / a, / tmp / a / b / und dann / tmp / a / b / c ausführen, da es in der C-API kein Äquivalent zum Flag -p gibt. Seien Sie sicher und ignorieren Sie die EEXISTS-Fehler, während Sie die oberen Ebenen ausführen.
quelle
("/tmp/",...)
,("/tmp/a/",...)
,("/tmp/a/b/",...)
,("/tmp/a/b/c/",...)
Hier ist mein Beispiel für Code (es funktioniert sowohl für Windows als auch für Linux):
Verwendung:
quelle
stat
(bezogen auf__STDC__
) keine Notwendigkeit für den Precompiler - Test.Es ist zu beachten, dass das Starten ab der C ++ 17-Dateisystemschnittstelle Teil der Standardbibliothek ist. Dies bedeutet, dass zum Erstellen von Verzeichnissen Folgendes möglich ist:
Mehr Infos hier: https://en.cppreference.com/w/cpp/filesystem/create_directory
Zusätzlich muss man bei gcc "-std = c ++ 17" für CFLAGS verwenden. Und "-lstdc ++ fs" zu LDLIBS. Letzteres wird möglicherweise in Zukunft nicht mehr benötigt.
quelle
Dies ähnelt dem vorherigen, funktioniert jedoch vorwärts durch die Zeichenfolge anstatt rekursiv rückwärts. Lässt errno mit dem richtigen Wert für den letzten Fehler. Wenn es einen führenden Schrägstrich gibt, gibt es eine zusätzliche Zeit durch die Schleife, die durch ein find_first_of () außerhalb der Schleife oder durch Erkennen des führenden / und der Einstellung vor 1 vermieden werden könnte. Die Effizienz ist gleich, unabhängig davon, ob wir von a eingerichtet werden erste Schleife oder ein Pre-Loop-Aufruf, und die Komplexität wäre (geringfügig) höher, wenn der Pre-Loop-Aufruf verwendet wird.
quelle
Sie sagten "C ++", aber jeder hier scheint an "Bash Shell" zu denken.
Überprüfen Sie den Quellcode zu gnu
mkdir
; Dann können Sie sehen, wie Sie die Shell-Befehle in C ++ implementieren.quelle
quelle
Also, ich brauche
mkdirp()
heute und fand die Lösungen auf dieser Seite zu kompliziert. Daher habe ich einen ziemlich kurzen Ausschnitt geschrieben, der leicht für andere kopiert werden kann, die über diesen Thread stolpern. Ein Wunder, warum wir so viele Codezeilen benötigen.mkdirp.h
mkdirp.cpp
Wenn Sie das Casting von Konstanten und das vorübergehende Ändern der Zeichenfolge nicht mögen, führen Sie einfach a
strdup()
undfree()
danach aus.quelle
Da dieser Beitrag in Google für "Create Directory Tree" einen hohen Rang einnimmt, werde ich eine Antwort veröffentlichen, die für Windows funktioniert - dies funktioniert mit der für UNICODE oder MBCS kompilierten Win32-API. Dies ist aus Marks Code oben portiert.
Da dies Windows ist, mit dem wir arbeiten, sind Verzeichnis-Trennzeichen BACK-Schrägstriche und keine Schrägstriche. Wenn Sie lieber Schrägstriche haben möchten, wechseln Sie
'\\'
zu'/'
Es wird funktionieren mit:
und
(dh: benötigt keinen abschließenden Schrägstrich, sodass Sie nicht danach suchen müssen.)
Beachten Sie, dass SHCreateDirectoryEx () veraltet ist und jederzeit aus zukünftigen Windows-Versionen entfernt werden kann, bevor Sie "Nur SHCreateDirectoryEx () in Windows verwenden" sagen .
quelle
c:\this\is\a/mixed/path\of\slashes
Regel sind Windows-Schrägstriche Backslashes. Was passieren sollte, ist, dass der Aufrufer den Pfad bereinigt und sicherstellt, dass alle Schrägstriche korrekt sind, bevor er diese Methode aufruft.Ich weiß, dass es eine alte Frage ist, aber sie taucht in den Google-Suchergebnissen häufig auf und die hier angegebenen Antworten sind nicht wirklich in C ++ oder etwas zu kompliziert.
Bitte beachten Sie, dass createDirTree () in meinem Beispiel sehr einfach ist, da das gesamte schwere Heben (Fehlerprüfung, Pfadüberprüfung) ohnehin von createDir () durchgeführt werden muss. Außerdem sollte createDir () true zurückgeben, wenn das Verzeichnis bereits vorhanden ist oder das Ganze nicht funktioniert.
So würde ich das in C ++ machen:
Natürlich wird die Funktion createDir () systemspezifisch sein und es gibt bereits genügend Beispiele in anderen Antworten, wie man sie für Linux schreibt, also habe ich beschlossen, sie zu überspringen.
quelle
Wenn dir nicht existiert, erstelle es:
quelle
Es wurden hier so viele Ansätze beschrieben, aber die meisten von ihnen erfordern eine harte Codierung Ihres Pfades in Ihren Code. Für dieses Problem gibt es eine einfache Lösung: QDir und QFileInfo, zwei Klassen von Qt-Frameworks. Da Sie sich bereits in einer Linux-Umgebung befinden, sollte es einfach sein, Qt zu verwenden.
Stellen Sie sicher, dass Sie Schreibzugriff auf diesen Pfad haben.
quelle
quelle
-p
Option ist das, wonach ich suche. Vielen Dank!Hier ist die rekursive C / C ++ - Funktion, mit der
dirname()
der Verzeichnisbaum von unten nach oben durchlaufen wird. Es wird angehalten, sobald es einen vorhandenen Vorfahren findet.quelle
Die anderen haben dir die richtige Antwort gegeben, aber ich dachte, ich würde eine andere nette Sache demonstrieren, die du tun kannst:
Erstellt die folgenden Pfade:
Mit den geschweiften Klammern können Sie mehrere Verzeichnisse gleichzeitig auf derselben Hierarchieebene
-p
erstellen , während die Option "übergeordnete Verzeichnisse nach Bedarf erstellen" bedeutet.quelle