Changer le répertoire de travail actuel en C++

Comment puis-je changer mon répertoire de travail actuel en C++ d'une manière agnostique?

j'ai trouvé direct.h le fichier d'en-tête, qui est compatible Windows, et le unistd.h, qui est compatible UNIX / POSIX.

36
demandé sur Palec 2010-08-15 01:20:59

8 réponses

chdir la fonction fonctionne sur les deux POSIX (man) et Windows (appelé _chdir là, mais un alias chdir existe).

les deux implémentations retournent zéro sur le succès et -1 sur l'erreur. Comme vous pouvez le voir dans la page de manuel, des valeurs errno plus distinguées sont possibles dans la variante POSIX, mais cela ne devrait pas vraiment faire de différence pour la plupart des cas d'utilisation.

41
répondu AndiDog 2016-10-24 14:20:04

Pour C++, boost:: filesystem:: current_path (setter et getter prototypes).

une bibliothèque de système de fichiers basée sur Boost.Système de fichiers sera ajouté à la norme.

15
répondu pepper_chico 2013-03-05 04:36:39

chdir() faire ce que vous voulez? Il fonctionne sous POSIX et Windows.

8
répondu Jeremy Friesner 2013-11-28 13:29:49

ce code d'exemple multiplateformes pour changer le répertoire de travail en utilisant POSIX chdir et MS _chdir recommander cette réponse. De même pour déterminer le répertoire de travail courant, l'analogue getcwd et _getcwd sont utilisés.

ces différences de plate-forme sont cachées derrière les macros cd et cwd.

selon la documentation,chdirsignature int chdir(const char *path)path est absolue ou relative. chdir renvoie 0 en cas de succès. getcwd est un peu plus compliqué parce qu'il a besoin (dans une variante) d'un tampon pour stocker le chemin récupéré comme vu dans char *getcwd(char *buf, size_t size). Il renvoie NULL en cas d'échec et un pointeur vers le même tampon passé en cas de succès. L'échantillon de code utilise directement ce pointeur de char retourné.

l'échantillon est basé sur @MarcD mais corrige une fuite de mémoire. De plus, je me suis efforcé pour la concision, pas de dépendances, et seulement l'échec/erreur de base vérifier et s'assurer qu'il fonctionne sur plusieurs plateformes (communes).

Je l'ai testé sur OSX 10.11.6, Centos7, et Win10. Pour OSX & Centos, j'ai utilisé g++ changedir.cpp -o changedir construire et courait ./changedir <path>.

sur Win10, j'ai construit avec cl.exe changedir.cpp /EHsc /nologo.

solution MVP

$ cat changedir.rpc

#ifdef _WIN32
#include <direct.h>
// MSDN recommends against using getcwd & chdir names
#define cwd _getcwd
#define cd _chdir
#else
#include "unistd.h"
#define cwd getcwd
#define cd chdir
#endif

#include <iostream>

char buf[4096]; // never know how much is needed

int main(int argc , char** argv) {

  if (argc > 1) {
    std::cout  << "CWD: " << cwd(buf, sizeof buf) << std::endl;

    // Change working directory and test for success
    if (0 == cd(argv[1])) {
      std::cout << "CWD changed to: " << cwd(buf, sizeof buf) << std::endl;
    }
  } else {
    std::cout << "No directory provided" << std::endl;
  }

  return 0;
}

liste OSX:

$ g++ changedir.c -o changedir

$ ./changedir test

CWD: / Users / Phil

La MDC a changé: /Users/Phil/test

Liste Centos:

$ g++ changedir.c -o changedir

$ ./changedir

Pas de répertoire fourni

$ ./ changedir does_not_exist

CWD: / home / phil

$ ./changedir Musique

CWD: / home / phil

CWD changé: /home/phil/Musique

$ ./changedir /

CWD: / home / phil

La MDC a changé: /

Win10 Listing

cl.exe changedir.cpp / EHsc / nologo

changedir.rpc

c:\Users\Phil > changer.test exe

CWD: c:\Users\Phil

CWD changée en: c:\Users\Phil\test

Note: utilisation de L'OSX clang et Centos gnu gcc derrière g++.

6
répondu Phil 2017-05-23 12:00:12

chdir(2). Si vous essayez de faire modifier le répertoire de travail de votre shell par votre programme - vous ne pouvez pas. Il ya beaucoup de réponses sur donc déjà aborder ce problème.

5
répondu Carl Norum 2010-08-14 21:28:32

vous voulez dire C ou c++? Ce sont des langues complètement différentes.

En C, la norme qui définit la langue ne couvre pas les répertoires. De nombreuses plateformes qui prennent en charge les répertoires ont un chdir fonction qui prend un char* ou const char* argument, mais même là où il existe l'en-tête où il est déclaré n'est pas standard. Il peut aussi y avoir des subtilités quant à la signification de l'argument (par exemple Windows a des répertoires par lecteur).

en C++, googler mène à chdir et _chdir, et suggère que Boost n'a pas d'interface avec chdir. Mais je ne dirai rien de plus puisque je ne connais pas le c++.

5
répondu Gilles 2010-08-14 22:23:39

Je n'arrive pas à croire que personne n'ait encore réclamé la prime sur celui-ci!!!

Voici une implémentation multi-plateforme qui récupère et modifie le répertoire courant en utilisant C++. Il suffit d'un peu de macro magic, pour lire la valeur d'argv[0], et pour définir quelques petites fonctions.

Voici le code pour changer de répertoire à l'emplacement du fichier exécutable qui est en cours d'exécution. Il peut facilement être adapté pour modifier le répertoire de travail courant de tout répertoire que vous voulez.

Code:

  #ifdef _WIN32
     #include "direct.h"
     #define PATH_SEP '\'
     #define GETCWD _getcwd
     #define CHDIR _chdir
  #else
     #include "unistd.h"
     #define PATH_SEP '/'
     #define GETCWD getcwd
     #define CHDIR chdir
  #endif

  #include <cstring>
  #include <string>
  #include <iostream>
  using std::cout;
  using std::endl;
  using std::string;

  string GetExecutableDirectory(const char* argv0) {
     string path = argv0;
     int path_directory_index = path.find_last_of(PATH_SEP);
     return path.substr(0 , path_directory_index + 1);
  }

  bool ChangeDirectory(const char* dir) {return CHDIR(dir) == 0;}

  string GetCurrentWorkingDirectory() {
     const int BUFSIZE = 4096;
     char buf[BUFSIZE];
     memset(buf , 0 , BUFSIZE);
     GETCWD(buf , BUFSIZE - 1);
     return buf;
  }

  int main(int argc , char** argv) {

     cout << endl << "Current working directory was : " << GetCurrentWorkingDirectory() << endl;
     cout << "Changing directory..." << endl;

     string exedir = GetExecutableDirectory(argv[0]);
     ChangeDirectory(exedir.c_str());

     cout << "Current working directory is now : " << GetCurrentWorkingDirectory() << endl;

     return 0;
  }

Sortie :

c:\Windows>c:\ctwoplus\progcode\test\CWD\cwd.exe

répertoire de travail actuel : c:\Windows En changeant le répertoire... Le répertoire de travail actuel est maintenant : c:\ctwoplus\progcode\test\CWD

c:\Windows>

2
répondu MarcD 2016-10-23 16:49:08

une bonne façon de changer le répertoire courant en C++ a été suggérée il y a longtemps par @pepper_chico. Cette solution utilise boost::filesystem::current_path().

Pour obtenir le répertoire de travail en cours d'utilisation:

namespace fs = boost::filesystem;
fs::path cur_working_dir(fs::current_path());

Pour définir le répertoire de travail en cours d'utilisation:

namespace fs = boost::filesystem;
fs::current_path(fs::system_complete( fs::path( "new_working_directory_path" ) ));    

Soufflet est l'auto-contenue fonctions d'assistance:

#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include <string>

namespace fs = boost::filesystem;    

fs::path get_cwd_pth()
{
  return fs::current_path();
}   

std::string get_cwd()
{ 
  return get_cwd_pth().c_str();
} 

void set_cwd(const fs::path& new_wd)
{
  fs::current_path(fs::system_complete( new_wd));
}   

void set_cwd(const std::string& new_wd)
{
  set_cwd( fs::path( new_wd));
}

Voici mon exemple de code complet sur la façon de configurer / mettre à jour le fonctionnement répertoire:

#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include <iostream>

namespace fs = boost::filesystem;

int main( int argc, char* argv[] )
{
  fs::path full_path;
  if ( argc > 1 )
  {
    full_path = fs::system_complete( fs::path( argv[1] ) );
  }  
  else
  {
    std::cout << "Usage:   tcd [path]" << std::endl;
  }

  if ( !fs::exists( full_path ) )
  {
    std::cout << "Not found: " << full_path.c_str() << std::endl;
    return 1;
  }

  if ( !fs::is_directory( full_path ))
  {
    std::cout << "Provided path is not a directory: " << full_path.c_str() << std::endl;
    return 1;
  }

  std::cout << "Old current working directory: " << boost::filesystem::current_path().c_str() << std::endl;

  fs::current_path(full_path);

  std::cout << "New current working directory: " << boost::filesystem::current_path().c_str() << std::endl;
  return 0;
}

Si boost installé sur votre système, vous pouvez utiliser la commande suivante pour compiler cet exemple:

g++ -o tcd app.cpp -lboost_filesystem -lboost_system
2
répondu Nikita 2016-10-24 23:10:54