Gibt es eine plattformunabhängige und eine dateisystemunabhängige Methode, um den vollständigen Pfad des Verzeichnisses abzurufen, aus dem ein Programm mit C / C ++ ausgeführt wird? Nicht zu verwechseln mit dem aktuellen Arbeitsverzeichnis. (Bitte schlagen Sie keine Bibliotheken vor, es sei denn, es handelt sich um Standardbibliotheken wie clib oder STL.)
(Wenn es keine plattform- / dateisystemunabhängige Methode gibt, sind auch Vorschläge willkommen, die unter Windows und Linux für bestimmte Dateisysteme funktionieren.)
c++
c
working-directory
Ashwin Nanjappa
quelle
quelle
argv[0]
, ist die Technik sehr betriebssystemabhängig.#include <windows.h>
tun, fügt Windows automatisch einenchar*
in den ausführbaren Pfad ein_pgmptr
. Sie müssen keine zusätzlichen Funktionen aufrufen oder Junk annehmen, wenn Sie nur unter Windows arbeiten._pgmptr
. In der MSDN-Dokumentation wird angegeben, dass die Variablen_pgmptr
und_wpgmptr
veraltet sind. Verwenden Sie stattdessen die Funktion_get_pgmptr(char**)
oder_get_wpgmptr(wchar_t**)
. MSDNAntworten:
Hier ist Code, um den vollständigen Pfad zur ausführenden App abzurufen:
Windows:
Linux:
quelle
/proc
Teil von mir ansieht , stirbt er ein wenig. Die ganze Welt ist nicht Linux, und selbst auf dieser einen Plattform/proc
sollte davon ausgegangen werden, dass sie von Version zu Version, von Bogen zu Bogen usw.char pBuf[256]; size_t len = sizeof(pBuf);
, um die Lösung klarer zu machen.Wenn Sie das aktuelle Verzeichnis beim ersten Start Ihres Programms abrufen, haben Sie effektiv das Verzeichnis, aus dem Ihr Programm gestartet wurde. Speichern Sie den Wert in einer Variablen und beziehen Sie sich später in Ihrem Programm darauf. Dies unterscheidet sich von dem Verzeichnis, in dem sich die aktuelle ausführbare Programmdatei befindet . Es ist nicht unbedingt dasselbe Verzeichnis. Wenn jemand das Programm über eine Eingabeaufforderung ausführt, wird das Programm aus dem aktuellen Arbeitsverzeichnis der Eingabeaufforderung ausgeführt, obwohl sich die Programmdatei an einer anderen Stelle befindet.
getcwd ist eine POSIX-Funktion und wird von allen POSIX-kompatiblen Plattformen sofort unterstützt. Sie müssten nichts Besonderes tun (außer die richtigen Header unistd.h unter Unix und direct.h unter Windows einzuschließen).
Da Sie ein C-Programm erstellen, wird es mit der Standard-C-Laufzeitbibliothek verknüpft, mit der ALLE Prozesse im System verknüpft sind (speziell gestaltete Ausnahmen werden vermieden), und diese Funktion wird standardmäßig enthalten. Die CRT wird niemals als externe Bibliothek betrachtet, da dies die grundlegende standardkonforme Schnittstelle zum Betriebssystem darstellt.
Unter Windows wurde die Funktion getcwd zugunsten von _getcwd nicht mehr unterstützt. Ich denke, Sie könnten es auf diese Weise verwenden.
quelle
Dies ist aus dem cplusplus Forum
Unter Windows:
Unter Linux:
Unter HP-UX:
quelle
error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)'
beim Kompilieren mit MinGW der Fehler angezeigt.Wenn Sie einen Standardweg ohne Bibliotheken wünschen: Nein. Das gesamte Konzept eines Verzeichnisses ist nicht im Standard enthalten.
Wenn Sie damit einverstanden sind, dass eine (tragbare) Abhängigkeit von einer nahezu standardmäßigen Bibliothek in Ordnung ist: Verwenden Sie die Dateisystembibliothek von Boost und fragen Sie nach dem initial_path () .
IMHO, das ist so nah wie möglich, mit gutem Karma (Boost ist ein gut etablierter Satz hochwertiger Bibliotheken)
quelle
Das Dateisystem TS ist jetzt ein Standard (und wird von gcc 5.3+ und clang 3.9+ unterstützt), sodass Sie die folgenden
current_path()
Funktionen verwenden können:In gcc (5.3+) müssen Sie Folgendes verwenden, um das Dateisystem einzuschließen:
und verknüpfe deinen Code mit
-lstdc++fs
flag.Wenn Sie das Dateisystem mit Microsoft Visual Studio verwenden möchten, lesen Sie dies .
quelle
1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs.
Downvoted, da das OP speziell nach dem aktuellen Pfad der ausführbaren Datei und nicht nach dem aktuellen Arbeitsverzeichnis fragt.Ich weiß, dass es sehr spät am Tag ist, eine Antwort auf diese Frage zu geben, aber ich fand, dass keine der Antworten für mich so nützlich war wie meine eigene Lösung. Ein sehr einfacher Weg, um den Pfad von Ihrem CWD zu Ihrem bin-Ordner zu erhalten, ist folgender:
Sie können dies jetzt einfach als Basis für Ihren relativen Pfad verwenden. So habe ich zum Beispiel diese Verzeichnisstruktur:
und ich möchte meinen Quellcode in bin kompilieren und ein Protokoll zum Testen schreiben. Ich kann diese Zeile einfach zu meinem Code hinzufügen.
Ich habe diesen Ansatz unter Linux mit vollständigem Pfad, Alias usw. ausprobiert und er funktioniert einwandfrei.
HINWEIS:
Wenn Sie unter Windows arbeiten, sollten Sie ein '\' als Dateitrennzeichen verwenden, nicht '/'. Sie müssen sich auch dem entziehen, zum Beispiel:
Ich denke, dies sollte funktionieren, wurde aber nicht getestet. Daher wäre ein Kommentar willkommen, wenn es funktioniert, oder ein Fix, wenn nicht.
quelle
argv[0]
ist eine sehr schöne Idee, aber leider bekomme ich unter Linux "./my_executable_name" oder "./make/my_executable_name". Grundsätzlich hängt es völlig davon ab, wie ich esNein, es gibt keinen Standardweg. Ich glaube, dass die C / C ++ - Standards nicht einmal die Existenz von Verzeichnissen (oder anderen Dateisystemorganisationen) berücksichtigen.
Unter Windows gibt GetModuleFileName () den vollständigen Pfad zur ausführbaren Datei des aktuellen Prozesses zurück, wenn der Parameter hModule auf NULL gesetzt ist . Ich kann nicht mit Linux helfen.
Außerdem sollten Sie klarstellen, ob Sie das aktuelle Verzeichnis oder das Verzeichnis möchten, in dem sich das Programmabbild / die ausführbare Datei befindet. Aus heutiger Sicht ist Ihre Frage in diesem Punkt etwas mehrdeutig.quelle
Unter Windows besteht die einfachste Möglichkeit darin, mit der
_get_pgmptr
Funktion instdlib.h
einen Zeiger auf eine Zeichenfolge abzurufen, die den absoluten Pfad zur ausführbaren Datei einschließlich des Namens der ausführbaren Datei darstellt.quelle
Vielleicht das aktuelle Arbeitsverzeichnis mit argv [0] verketten? Ich bin nicht sicher, ob das unter Windows funktionieren würde, aber es funktioniert unter Linux.
Beispielsweise:
Beim Ausführen wird Folgendes ausgegeben:
quelle
Für Win32 sollte GetCurrentDirectory den Trick machen.
quelle
Sie können argv [0] nicht für diesen Zweck verwenden. Normalerweise enthält es den vollständigen Pfad zur ausführbaren Datei, aber nicht unbedingt. Der Prozess kann mit einem beliebigen Wert im Feld erstellt werden.
Beachten Sie auch, dass das aktuelle Verzeichnis und das Verzeichnis mit der ausführbaren Datei zwei verschiedene Dinge sind, sodass getcwd () Ihnen auch nicht hilft.
Verwenden Sie unter Windows GetModuleFileName (), unter Linux read / dev / proc / procID / .. Dateien.
quelle
Nur um sich hier verspätet anzuhäufen, ...
Es gibt keine Standardlösung, da die Sprachen unabhängig von den zugrunde liegenden Dateisystemen sind. Wie andere bereits gesagt haben, liegt das Konzept eines verzeichnisbasierten Dateisystems außerhalb des Bereichs der c / c ++ - Sprachen.
Darüber hinaus möchten Sie nicht das aktuelle Arbeitsverzeichnis, sondern das Verzeichnis, in dem das Programm ausgeführt wird. Dabei muss berücksichtigt werden, wie das Programm dort angekommen ist, wo es sich befindet - dh, es wurde als neuer Prozess über eine Verzweigung usw. erzeugt. Um das Verzeichnis abzurufen, in dem ein Programm ausgeführt wird, müssen Sie, wie die Lösungen gezeigt haben, diese Informationen aus den Prozesssteuerungsstrukturen des betreffenden Betriebssystems abrufen. Dies ist die einzige Berechtigung für diese Frage. Somit ist es per Definition eine betriebssystemspezifische Lösung.
quelle
Für Windows-Systeme an der Konsole können Sie den
dir
Befehl system ( ) verwenden. Die Konsole bietet Informationen zu Verzeichnissen usw. Weitere Informationen zumdir
Befehl finden Sie untercmd
. Aber für Unix-ähnliche Systeme weiß ich nicht ... Wenn dieser Befehl ausgeführt wird, lesen Sie den Befehl bash.ls
zeigt kein Verzeichnis an ...Beispiel:
quelle
quelle
Auf POSIX-Plattformen können Sie getcwd () verwenden .
Unter Windows können Sie _getcwd () verwenden , da die Verwendung von getcwd () veraltet ist.
Wenn Boost für Standardbibliotheken Standard genug für Sie wäre, hätte ich Boost :: filesystem vorgeschlagen, aber sie scheinen die Pfadnormalisierung aus dem Vorschlag entfernt zu haben. Möglicherweise müssen Sie warten, bis TR2 für eine vollständige Standardlösung verfügbar ist .
quelle
Für relative Pfade habe ich Folgendes getan. Ich bin mir des Alters dieser Frage bewusst und möchte einfach eine einfachere Antwort liefern, die in den meisten Fällen funktioniert:
Angenommen, Sie haben einen Pfad wie diesen:
Aus irgendeinem Grund funktionieren in Eclipse erstellte Linux-erstellte ausführbare Dateien problemlos. Windows wird jedoch sehr verwirrt, wenn ein Pfad wie dieser angegeben wird, mit dem gearbeitet werden kann!
Wie oben erwähnt, gibt es verschiedene Möglichkeiten, um den aktuellen Pfad zur ausführbaren Datei abzurufen. Der einfachste Weg, den ich finde, funktioniert jedoch in den meisten Fällen, wenn Sie ihn an die Vorderseite Ihres Pfads anhängen:
Wenn Sie nur "./" hinzufügen, werden Sie sortiert! :) Dann können Sie mit dem Laden aus einem beliebigen Verzeichnis beginnen, solange es sich um die ausführbare Datei selbst handelt.
BEARBEITEN: Dies funktioniert nicht, wenn Sie versuchen, die ausführbare Datei aus Code :: -Blöcken zu starten, wenn dies die verwendete Entwicklungsumgebung ist. Aus irgendeinem Grund werden Code :: -Blöcke nicht richtig geladen ...: D.
EDIT2: Einige neue Dinge, die ich gefunden habe, sind: Wenn Sie einen statischen Pfad wie diesen in Ihrem Code angeben (Angenommen, Example.data müssen geladen werden):
Wenn Sie dann Ihre App aus dem tatsächlichen Verzeichnis starten (oder unter Windows eine Verknüpfung erstellen und das Arbeitsverzeichnis auf Ihr App-Verzeichnis festlegen), funktioniert dies folgendermaßen. Beachten Sie dies beim Debuggen von Problemen im Zusammenhang mit fehlenden Ressourcen- / Dateipfaden. (Insbesondere in IDEs, die beim Starten einer Build-Exe von der IDE das falsche Arbeitsverzeichnis festlegen)
quelle
Eine Bibliothekslösung (obwohl ich weiß, dass dies nicht verlangt wurde). Wenn Sie zufällig Qt verwenden:
QCoreApplication::applicationDirPath()
quelle
Nur meine zwei Cent, aber funktioniert der folgende Code in C ++ 17 nicht portabel?
Scheint zumindest unter Linux für mich zu funktionieren.
Basierend auf der vorherigen Idee habe ich jetzt:
Mit Implementierung:
Und Initialisierungstrick in
main()
:Danke @Sam Redway für die argv [0] Idee. Und natürlich verstehe ich, dass es C ++ 17 viele Jahre nicht gab, als das OP die Frage stellte.
quelle
Boost Filesystem
initial_path()
verhält sich wie POSIXgetcwd()
und tut auch nicht das, was Sie wollen, aber das Anhängenargv[0]
an eines von beiden sollte es tun.Sie können feststellen, dass das Ergebnis nicht immer hübsch ist - Sie erhalten möglicherweise Dinge wie
/foo/bar/../../baz/a.out
oder/foo/bar//baz/a.out
, aber ich glaube, dass es immer zu einem gültigen Pfad führt, der die ausführbare Datei benennt (beachten Sie, dass aufeinanderfolgende Schrägstriche in einem Pfad zu einem reduziert werden).Ich habe zuvor eine Lösung mit
envp
(das dritte Argument,main()
das unter Linux funktioniert hat, aber unter Windows nicht funktioniert hat) geschrieben. Daher empfehle ich im Wesentlichen dieselbe Lösung wie zuvor, aber mit der zusätzlichen Erklärung, warum sie tatsächlich korrekt ist auch wenn die Ergebnisse nicht schön sind.quelle
Wie Minok erwähnte, gibt es keine solche Funktionalität, die im C-Standard oder C ++ - Standard angegeben ist. Dies wird als rein betriebssystemspezifische Funktion angesehen und ist beispielsweise im POSIX-Standard festgelegt.
Thorsten79 hat gute Vorschläge gemacht, es ist Boost.Filesystem Bibliothek. Dies kann jedoch unpraktisch sein, wenn Sie für Ihr Programm keine Abhängigkeiten zur Verbindungszeit in binärer Form haben möchten.
Eine gute Alternative, die ich empfehlen würde, ist die Sammlung von STLSoft C ++ - Bibliotheken mit 100% Headern. Matthew Wilson (Autor von Büchern, die man unbedingt über C ++ lesen muss). Es gibt eine tragbare Fassade PlatformSTL bietet Zugriff auf die systemspezifische API: WinSTL für Windows und UnixSTL unter Unix, ist also eine tragbare Lösung. Alle systemspezifischen Elemente werden mithilfe von Merkmalen und Richtlinien angegeben, sodass es sich um ein erweiterbares Framework handelt. Natürlich gibt es eine Dateisystembibliothek.
quelle
Der Linux-Bash-Befehl, dessen Progname einen Pfad zum Programm meldet.
Selbst wenn man den Befehl which in Ihrem Programm ausgeben und die Ausgabe in eine tmp-Datei leiten könnte und das Programm anschließend diese tmp-Datei liest, wird es Ihnen nicht sagen, ob dieses Programm dasjenige ist, das ausgeführt wird. Hier erfahren Sie nur, wo sich ein Programm mit diesem Namen befindet.
Erforderlich ist es, Ihre Prozess-ID-Nummer zu erhalten und den Pfad zum Namen zu analysieren
In meinem Programm möchte ich wissen, ob das Programm aus dem bin-Verzeichnis des Benutzers oder aus einem anderen im Pfad oder aus / usr / bin ausgeführt wurde. / usr / bin würde die unterstützte Version enthalten. Mein Gefühl ist, dass es unter Linux die eine Lösung gibt, die portabel ist.
quelle
Verwenden Sie
realpath()
instdlib.h
wie folgt:quelle
Funktioniert mit C ++ 11 unter Verwendung des experimentellen Dateisystems und C ++ 14-C ++ 17 unter Verwendung des offiziellen Dateisystems.
application.h:
application.cpp:
quelle
std
. Um dies zu vermeiden, können Sie sowohl die Namespacesstd::filesystem
alsstd::experimental::filesystem
auch einen dritten Namespace Ihrer Wahlusing std::filesystem::path
hinzufügen oder einfach verwenden , wenn Sie nichts dagegen haben, die Deklaration vonpath
zum globalen Namespace hinzuzufügen .