Comment puis-je obtenir le répertoire d’un programme?

Existe-t-il une méthode indépendante de la plate-forme et indépendante du système de fichiers pour obtenir le chemin complet du répertoire à partir duquel un programme est exécuté en utilisant C / C ++? Ne pas confondre avec le répertoire de travail actuel. (Merci de ne pas suggérer les bibliothèques sauf si elles sont standard comme clib ou STL.)

(S’il n’y a pas de méthode indépendante de la plate-forme / du système de fichiers, les suggestions qui fonctionnent sous Windows et Linux pour des systèmes de fichiers spécifiques sont également les bienvenues).

Voici le code pour obtenir le chemin complet de l’application en cours d’exécution:

Les fenêtres:

 int bytes = GetModuleFileName(NULL, pBuf, len); if(bytes == 0) return -1; else return bytes; 

Linux:

 char szTmp[32]; sprintf(szTmp, "/proc/%d/exe", getpid()); int bytes = MIN(readlink(szTmp, pBuf, len), len - 1); if(bytes >= 0) pBuf[bytes] = '\0'; return bytes; 

Si vous récupérez le répertoire en cours lorsque votre programme démarre pour la première fois, vous avez effectivement le répertoire à partir duquel votre programme a été démarré. Stockez la valeur dans une variable et consultez-la plus tard dans votre programme. Ceci est distinct du répertoire qui contient le fichier de programme exécutable actuel . Ce n’est pas nécessairement le même répertoire; Si quelqu’un exécute le programme à partir d’une invite de commande, le programme est exécuté à partir du répertoire de travail actuel de l’invite de commandes, même si le fichier du programme est situé ailleurs.

getcwd est une fonction POSIX prise en charge par toutes les plates-formes compatibles POSIX. Vous n’auriez rien à faire de spécial (à part l’inclusion des en-têtes droit unistd.h sur Unix et direct.h sur Windows).

Comme vous créez un programme C, il sera lié à la bibliothèque d’exécution c par défaut qui est liée à TOUS les processus du système (exceptions spécialement conçues évitées) et inclura cette fonction par défaut. Le CRT n’est jamais considéré comme une bibliothèque externe car cela fournit l’interface standard de base au système d’exploitation.

Sur Windows, la fonction getcwd est devenue obsolète en faveur de _getcwd. Je pense que vous pourriez l’utiliser de cette façon.

 #include  /* defines FILENAME_MAX */ #ifdef WINDOWS #include  #define GetCurrentDir _getcwd #else #include  #define GetCurrentDir getcwd #endif char cCurrentPath[FILENAME_MAX]; if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { return errno; } cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ printf ("The current working directory is %s", cCurrentPath); 

Ceci est du forum cplusplus

Sur les fenêtres:

 #include  #include  std::ssortingng getexepath() { char result[ MAX_PATH ]; return std::ssortingng( result, GetModuleFileName( NULL, result, MAX_PATH ) ); } 

Sous Linux:

 #include  #include  #include  std::ssortingng getexepath() { char result[ PATH_MAX ]; ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX ); return std::ssortingng( result, (count > 0) ? count : 0 ); } 

Sur HP-UX:

 #include  #include  #define _PSTAT64 #include  #include  #include  std::ssortingng getexepath() { char result[ PATH_MAX ]; struct pst_status ps; if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0) return std::string(); if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0) return std::string(); return std::string( result ); } 

Si vous voulez une méthode standard sans bibliothèques: Non. Le concept entier d’un répertoire n’est pas inclus dans la norme.

Si vous convenez que certaines dépendances (portables) sur une lib proche de la norme sont acceptables: utilisez la bibliothèque du système de fichiers de Boost et demandez le chemin_initial () .

IMHO c’est aussi proche que possible, avec un bon karma (Boost est un ensemble de bibliothèques de haute qualité bien établi)

Le système de fichiers TS est maintenant un standard (et supporté par gcc 5.3+ et clang 3.9+), vous pouvez donc utiliser la fonction current_path() :

 std::ssortingng path = std::experimental::filesystem::current_path(); 

Dans gcc (5.3+) pour inclure le système de fichiers que vous devez utiliser:

 #include  

et liez votre code avec l’ -lstdc++fs .

Si vous souhaitez utiliser le système de fichiers avec Microsoft Visual Studio, lisez ceci .

Je sais qu’il est très tard dans la journée de répondre à cette question, mais j’ai trouvé qu’aucune des réponses ne m’était aussi utile que ma propre solution. Un moyen très simple d’obtenir le chemin de votre CWD vers votre dossier bin est le suivant:

 int main(int argc, char* argv[]) { std::ssortingng argv_str(argv[0]); std::ssortingng base = argv_str.substr(0, argv_str.find_last_of("/")); } 

Vous pouvez maintenant simplement l’utiliser comme base pour votre chemin relatif. Donc, par exemple, j’ai cette structure de répertoire:

 main ----> test ----> src ----> bin 

et je veux comstackr mon code source pour bin et écrire un journal pour tester je peux juste append cette ligne à mon code.

 std::ssortingng pathToWrite = base + "/../test/test.log"; 

J’ai essayé cette approche sous Linux en utilisant un chemin complet, un alias, etc. et cela fonctionne très bien.

REMARQUE:

Si vous êtes sur Windows, vous devez utiliser un “\” comme séparateur de fichier et non pas “/”. Vous devrez aussi y échapper, par exemple:

 std::ssortingng base = argv[0].substr(0, argv[0].find_last_of("\\")); 

Je pense que cela devrait fonctionner, mais que je n’ai pas testé, alors si vous aviez un commentaire ou un correctif, vos commentaires seraient appréciés.

Non, il n’y a pas de moyen standard. Je pense que les normes C / C ++ ne tiennent même pas compte de l’existence de répertoires (ou d’autres organisations de systèmes de fichiers).

Sous Windows, le GetModuleFileName () renvoie le chemin d’access complet au fichier exécutable du processus en cours lorsque le paramètre hModule est défini sur NULL . Je ne peux pas aider avec Linux.

Vous devez également préciser si vous voulez le répertoire en cours ou le répertoire dans lequel se trouve l’image / l’exécutable du programme. En l’état, votre question est un peu ambiguë sur ce point.

Peut-être concaténer le répertoire de travail actuel avec argv [0]? Je ne sais pas si cela fonctionnerait sous Windows, mais cela fonctionne sous Linux.

Par exemple:

 #include  #include  #include  int main(int argc, char **argv) { char the_path[256]; getcwd(the_path, 255); strcat(the_path, "/"); strcat(the_path, argv[0]); printf("%s\n", the_path); return 0; } 

Lorsqu’il est exécuté, il génère:

jeremy @ jeremy-desktop: ~ / Desktop $ ./test
/home/jeremy/Desktop/./test

Vous ne pouvez pas utiliser argv [0] à cette fin, généralement il contient le chemin complet de l’exécutable, mais pas nécessairement – le processus peut être créé avec une valeur arbitraire dans le champ.

De plus, le répertoire en cours et le répertoire avec l’exécutable sont deux choses différentes, donc getcwd () ne vous aidera pas non plus.

Sous Windows, utilisez GetModuleFileName (), sous Linux, lisez les fichiers / dev / proc / procID / ..

Pour Win32, GetCurrentDirectory devrait faire l’affaire.

Pour le système Windows à la console, vous pouvez utiliser la commande system ( dir ). Et la console vous donne des informations sur le répertoire et etc. Lisez à propos de la commande dir à cmd . Mais pour les systèmes de type Unix, je ne sais pas … Si cette commande est exécutée, lisez la commande bash. ls n’affiche pas le répertoire …

Exemple:

 int main() { system("dir"); system("pause"); //this wait for Enter-key-press; return 0; } 

Juste pour emstackr tardivement ici, …

Il n’y a pas de solution standard, car les langages sont indépendants des systèmes de fichiers sous-jacents, comme d’autres l’ont dit, le concept de système de fichiers basé sur un répertoire ne relève pas des langages c / c ++.

en plus de cela, vous ne voulez pas le répertoire de travail en cours, mais le répertoire dans lequel le programme est exécuté, qui doit tenir compte de la manière dont le programme est arrivé – c.-à-d. Pour obtenir le répertoire dans lequel s’exécute un programme, comme l’ont démontré les solutions, vous devez obtenir ces informations auprès des structures de contrôle de processus du système d’exploitation en question, qui est la seule autorité sur cette question. Ainsi, par définition, c’est une solution spécifique au système d’exploitation.

Sous Windows, le moyen le plus simple consiste à utiliser la fonction _get_pgmptr dans stdlib.h pour obtenir un pointeur sur une chaîne qui représente le chemin absolu de l’exécutable, y compris le nom du fichier exécutable.

 char* path; _get_pgmptr(&path); printf(path); // Example output: C:/Projects/Hello/World.exe 
 #include  using namespace std; // The directory path returned by native GetCurrentDirectory() no end backslash ssortingng getCurrentDirectoryOnWindows() { const unsigned long maxDir = 260; char currentDir[maxDir]; GetCurrentDirectory(maxDir, currentDir); return ssortingng(currentDir); } 

La commande linux bash dont progname indiquera un chemin d’access au programme.

Même si vous pouviez émettre la commande quel que soit votre programme et diriger la sortie vers un fichier Il vous indique uniquement où se trouve un programme portant ce nom.

Ce qu’il faut, c’est obtenir votre numéro d’identification de processus et parsingr le chemin d’access au nom

Dans mon programme, je veux savoir si le programme a été exécuté à partir du répertoire bin de l’utilisateur ou d’un autre dans le chemin ou à partir de / usr / bin. / usr / bin contiendrait la version prise en charge. Mon sentiment est que sous Linux, il existe une solution portable.

Pour les chemins relatifs, voici ce que j’ai fait. Je suis conscient de l’âge de cette question, je veux simplement apporter une réponse plus simple qui fonctionne dans la majorité des cas:

Disons que vous avez un chemin comme celui-ci:

 "path/to/file/folder" 

Pour une raison quelconque, les exécutables construits en Linux dans eclipse fonctionnent bien avec cela. Cependant, Windows devient très confus si on lui donne un chemin comme ça pour travailler avec!

Comme indiqué ci-dessus, il existe plusieurs manières d’obtenir le chemin d’access actuel à l’exécutable, mais la manière la plus simple de trouver un travail dans la majorité des cas consiste à append ceci au FRONT de votre chemin:

 "./path/to/file/folder" 

Ajouter simplement “./” devrait vous permettre de sortinger! 🙂 Ensuite, vous pouvez commencer à charger depuis le répertoire de votre choix, à condition que ce soit avec l’exécutable lui-même.

EDIT: Cela ne fonctionnera pas si vous essayez de lancer l’exécutable à partir du code :: blocks si c’est l’environnement de développement utilisé, comme pour une raison quelconque, le code :: blocks ne charge pas bien les choses …: D

EDIT2: Quelques nouvelles choses que j’ai trouvées sont que si vous spécifiez un chemin statique comme celui-ci dans votre code (Assumant Example.data est quelque chose que vous devez charger):

 "resources/Example.data" 

Si vous lancez ensuite votre application à partir du répertoire réel (ou sous Windows, vous créez un raccourci, et définissez le répertoire de travail sur votre répertoire d’application), cela fonctionnera comme ça. Gardez cela à l’esprit lorsque vous déboguez des problèmes liés aux chemins de ressources / fichiers manquants. (Surtout dans les IDE qui définissent le mauvais répertoire de travail lors du lancement d’un build exe depuis l’EDI)

Sur les plates-formes POSIX, vous pouvez utiliser getcwd () .

Sous Windows, vous pouvez utiliser _getcwd () , car l’utilisation de getcwd () est obsolète.

Pour les bibliothèques standard, si Boost était suffisamment standard pour vous, j’aurais suggéré Boost :: fileystem, mais elles semblent avoir supprimé la normalisation des chemins de la proposition. Vous devrez peut-être attendre que TR2 soit facilement disponible pour une solution entièrement standard.

L’ initial_path() Boost Filesystem se comporte comme getcwd() de POSIX, et ce que vous voulez non plus, mais append argv[0] à l’un d’eux devrait le faire.

Vous remarquerez peut-être que le résultat n’est pas toujours joli – vous pouvez obtenir des choses comme /foo/bar/../../baz/a.out ou /foo/bar//baz/a.out , mais je crois que il en résulte toujours un chemin valide qui nomme l’exécutable (notez que les barres obliques consécutives dans un chemin sont réduites à un).

J’ai déjà écrit une solution en utilisant envp (le troisième argument de main() qui fonctionnait sous Linux mais ne semblait pas fonctionner sur Windows, donc je recommande essentiellement la même solution que quelqu’un d’autre auparavant, mais avec l’explication supplémentaire de la raison c’est effectivement correct même si les résultats ne sont pas beaux.

Comme le mentionne Minok , il n’existe pas de fonctionnalité spécifiée dans la norme ini C ou la norme C ++. Ceci est considéré comme une fonctionnalité spécifique au système d’exploitation et est spécifié dans la norme POSIX, par exemple.

Thorsten79 a donné une bonne suggestion, il s’agit de la bibliothèque Boost.Filesystem. Cependant, cela peut être gênant si vous ne voulez pas avoir de dépendances de temps de lien sous forme binary pour votre programme.

Une bonne alternative que je recommanderais est la collection des bibliothèques STLSoft C ++ à 100% en-têtes. Matthew Wilson (auteur de livres incontournables sur C ++). Il existe une façade portable PlatformSTL donne access à une API spécifique au système: WinSTL pour Windows et UnixSTL sur Unix, elle est donc une solution portable. Tous les éléments spécifiques au système sont spécifiés avec l’utilisation de traits et de stratégies. Il s’agit donc d’une structure extensible. Bien sûr, il existe une bibliothèque de système de fichiers.

Une solution de bibliothèque (bien que je sache que cela n’a pas été demandé). Si vous utilisez Qt: QCoreApplication::applicationDirPath()