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.
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.
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 .
chdir()
fait-il ce que vous voulez? Il fonctionne sous POSIX et Windows.
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)
où 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
.
$ 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;
}
$ g ++ changéir.c -o changéir
$ ./changé test
CWD:/Utilisateurs/Phil
CWD a été remplacé par:/Users/Phil/testing
$ 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: /
cl.exe changedir.cpp/EHsc/nologo
changedir.cpptest 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++
.
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.
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++.
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
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>
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
}