web-dev-qa-db-fra.com

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 indépendante de la plateforme?

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

42
sparkFinder

La fonction chdir fonctionne à la fois sur POSIX ( manpage ) et Windows (appelé _chdir mais un alias chdir existe).

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

47
AndiDog

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

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

15
pepper_chico

chdir() fait-il ce que vous voulez? Il fonctionne sous POSIX et Windows.

8
Jeremy Friesner

Cet exemple de code multiplateforme pour changer le répertoire de travail à l'aide de POSIX chdir et MS _chdir Comme recommandé dans cette réponse . De même pour déterminer le répertoire de travail courant, les analogues 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, la signature de chdir est int chdir(const char *path)path est absolu ou relatif. chdir renverra 0 en cas de succès. getcwd est un peu plus compliqué car 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'exemple de code utilise directement ce pointeur char retourné.

L'échantillon est basé sur @ MarcD mais corrige une fuite de mémoire. De plus, je me suis efforcé de faire de la concision, pas de dépendances, et seulement de vérifier les échecs/erreurs de base et de m'assurer qu'il fonctionne sur plusieurs plates-formes (courantes).

Je l'ai testé sur OSX 10.11.6, Centos7 et Win10. Pour OSX & Centos, j'ai utilisé g++ changedir.cpp -o changedir Pour créer et exécuter en tant que ./changedir <path>.

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

Solution MVP

$ cat changedir.cpp

#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 ++ changéir.c -o changéir
$ ./changé test
CWD:/Utilisateurs/Phil
CWD a été remplacé par:/Users/Phil/testing

Liste Centos:

$ g ++ changéir.c -o changéir
$ ./changé
Aucun répertoire fourni
$ ./changéir_pas_exister
CWD:/home/phil
$ ./changedir Musique
CWD:/home/phil
CWD remplacé par:/home/phil/Music
$ ./changé /
CWD:/home/phil
CWD remplacé par: /

Liste Win10

cl.exe changedir.cpp/EHsc/nologo
changedir.cpp

test c:\Users\Phil> changedir.exe
CWD: c:\Users\Phil
CWD changé en: c:\Users\Phil\test

Remarque: OSX utilise clang et Centos gnu gcc derrière g++.

8
Phil

Vous voulez chdir(2) . Si vous essayez de faire changer votre programme le répertoire de travail de votre Shell - vous ne pouvez pas. Il y a beaucoup de réponses sur SO déjà en train de résoudre ce problème.

5
Carl Norum

Voulez-vous 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 plates-formes qui prennent en charge les répertoires ont une fonction chdir 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 également y avoir des subtilités quant à la signification de l'argument (par exemple, Windows a des répertoires par lecteur).

En C++, la recherche sur Google mène à chdir et _chdir, et suggère que Boost n'a pas d'interface avec chdir. Mais je ne commenterai pas plus car je ne connais pas C++.

5
Gilles

Une belle méthode multiplateforme pour changer le répertoire actuel 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 actuel, utilisez:

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

Pour définir le répertoire de travail actuel, utilisez:

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

Ci-dessous les fonctions d'aide autonomes:

#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 définir/obtenir le répertoire de travail actuel:

#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 est installé sur votre système, vous pouvez utiliser la commande suivante pour compiler cet exemple:

g++ -o tcd app.cpp -lboost_filesystem -lboost_system
3
Nikita

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

Voici une implémentation multiplateforme qui obtient et modifie le répertoire de travail actuel à l'aide de C++. Il suffit d'un peu de macro magie, de lire la valeur de argv [0], et de définir quelques petites fonctions.

Voici le code pour changer les répertoires à l'emplacement du fichier exécutable qui s'exécute actuellement. Il peut facilement être adapté pour changer le répertoire de travail actuel en n'importe quel répertoire de votre choix.

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;
  }

Production :

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

Le répertoire de travail actuel était: c:\Windows Changer de répertoire ... Le répertoire de travail actuel est maintenant: c:\ctwoplus\progcode\test\CWD

c:\Windows>

2
MarcD

Maintenant, avec C++ 17, il est possible d'utiliser std::filesystem::current_path :

#include <filesystem>
int main() {
    auto path = std::filesystem::current_path(); //getting path
    std::filesystem::current_path(path); //setting path
}
1
João Paulo