it-swarm.com.de

Ändern Sie das aktuelle Arbeitsverzeichnis in C ++

Wie kann ich mein aktuelles Arbeitsverzeichnis in C++ plattformunabhängig ändern?

Ich fand die direct.h Header-Datei, die Windows-kompatibel ist, und die unistd.h, das UNIX/POSIX-kompatibel ist.

42
sparkFinder

Die Funktion chdir funktioniert sowohl unter POSIX ( manpage ) als auch unter Windows (genannt _chdir dort existiert aber ein Alias ​​chdir).

Beide Implementierungen geben bei Erfolg Null und bei Fehlern -1 zurück. Wie Sie in der Manpage sehen können, sind in der POSIX-Variante differenziertere Errno-Werte möglich, aber das sollte für die meisten Anwendungsfälle eigentlich keinen Unterschied machen.

47
AndiDog

Für C++ boost :: filesystem :: current_path (Setter- und Getter-Prototypen).

Eine Dateisystembibliothek basierend auf Boost.Filesystem wird zum Standard hinzugefügt .

15
pepper_chico

Macht chdir() was Sie wollen? Es funktioniert sowohl unter POSIX als auch unter Windows.

8
Jeremy Friesner

Dieser plattformübergreifende Beispielcode zum Ändern des Arbeitsverzeichnisses mit POSIX chdir und MS _chdir, Wie in diese Antwort empfohlen. Ebenso werden zur Ermittlung des aktuellen Arbeitsverzeichnisses die analogen getcwd und _getcwd verwendet.

Diese Plattformunterschiede verbergen sich hinter den Makros cd und cwd.

Gemäß der Dokumentation ist die Signatur von chdirint chdir(const char *path), wobei path absolut oder relativ ist. chdir gibt bei Erfolg 0 zurück. getcwd ist etwas komplizierter, da es (in einer Variante) einen Puffer benötigt, um den abgerufenen Pfad zu speichern, wie in char *getcwd(char *buf, size_t size) zu sehen. Bei einem Fehler wird NULL und bei Erfolg ein Zeiger auf denselben übergebenen Puffer zurückgegeben. Das Codebeispiel verwendet diesen zurückgegebenen Zeichenzeiger direkt.

Das Beispiel basiert auf @ MarcDs, behebt jedoch einen Speicherverlust. Außerdem bemühte ich mich um Präzision, keine Abhängigkeiten und nur um eine grundlegende Fehler-/Fehlerprüfung sowie um die Sicherstellung, dass diese auf mehreren (gemeinsamen) Plattformen funktioniert.

Ich habe es unter OSX 10.11.6, Centos7 und Win10 getestet. Für OSX & Centos habe ich g++ changedir.cpp -o changedir Zum Erstellen verwendet und als ./changedir <path> Ausgeführt.

Auf Win10 habe ich mit cl.exe changedir.cpp /EHsc /nologo Gebaut.

MVP-Lösung

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

OSX-Liste:

$ g ++ changedir.c -o changedir
$ ./geänderter Test
CWD:/Users/Phil
CWD geändert in:/Users/Phil/testing

Centos Listing:

$ g ++ changedir.c -o changedir
$ ./changedir
Kein Verzeichnis angegeben
$ ./changedir does_not_exist
CWD:/home/phil
$ ./Ihre Musik geändert
CWD:/home/phil
CWD geändert in:/home/phil/Music
$ ./changedir /
CWD:/home/phil
CWD geändert in: /

Win10 Listing

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

c:\Users\Phil> changedir.exe Test
CWD: c:\Users\Phil
CWD wurde geändert in: c:\Users\Phil\test

Hinweis: OSX verwendet clang und Centos gnu gcc hinter g++.

8
Phil

Sie möchten chdir(2) . Wenn Sie versuchen, Ihr Programm das Arbeitsverzeichnis Ihrer Shell ändern zu lassen, können Sie dies nicht. Es gibt viele Antworten auf SO das Problem bereits ansprechen.

5
Carl Norum

Meinten Sie C oder C++? Das sind ganz andere Sprachen.

In C deckt der Standard, der die Sprache definiert, keine Verzeichnisse ab. Viele Plattformen, die Verzeichnisse unterstützen, haben eine chdir -Funktion, die ein char* oder const char* Argument, aber selbst wenn es existiert, ist der Header, in dem es deklariert ist, nicht Standard. Es kann auch Feinheiten geben, was das Argument bedeutet (z. B. Windows hat Verzeichnisse pro Laufwerk).

In C++ führt Googeln zu chdir und _chdir und schlägt vor, dass Boost keine Schnittstelle zu chdir hat. Aber ich werde nicht weiter darauf eingehen, da ich C++ nicht kenne.

5
Gilles

Eine gute plattformübergreifende Möglichkeit, das aktuelle Verzeichnis in C++ zu ändern, wurde vor langer Zeit von @pepper_chico vorgeschlagen. Diese Lösung verwendet boost::filesystem::current_path() .

Verwenden Sie zum Abrufen des aktuellen Arbeitsverzeichnisses Folgendes:

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

Um das aktuelle Arbeitsverzeichnis einzustellen, verwenden Sie:

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

Bellow ist die in sich geschlossenen Hilfsfunktionen:

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

Hier ist mein komplettes Codebeispiel zum Festlegen/Abrufen des aktuellen Arbeitsverzeichnisses:

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

Wenn boost auf Ihrem System installiert ist, können Sie den folgenden Befehl verwenden, um dieses Beispiel zu kompilieren:

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

Ich kann nicht glauben, dass noch niemand das Kopfgeld für dieses Spiel beansprucht hat !!!

Hier ist eine plattformübergreifende Implementierung, die das aktuelle Arbeitsverzeichnis mit C++ abruft und ändert. Alles was es braucht ist ein wenig Makromagie, um den Wert von argv [0] zu lesen und ein paar kleine Funktionen zu definieren.

Hier ist der Code zum Wechseln der Verzeichnisse zum Speicherort der derzeit ausgeführten ausführbaren Datei. Es kann einfach angepasst werden, um das aktuelle Arbeitsverzeichnis in ein beliebiges Verzeichnis zu ändern.

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

Ausgabe :

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

Das aktuelle Arbeitsverzeichnis war: c:\Windows Verzeichnis wird geändert ... Das aktuelle Arbeitsverzeichnis ist jetzt: c:\ctwoplus\progcode\test\CWD

c:\Windows>

2
MarcD

Nun ist es mit C++ 17 möglich, 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