Изменение текущего рабочего каталога в C++

Как я могу изменить свой текущий рабочий каталог на C++ агностическим способом платформы?

нашел direct.h файл заголовка, который совместим с Windows, и unistd.h, который совместим с UNIX / POSIX.

8 ответов


на chdir функция работает на обоих POSIX (manpage) и Windows (называется _chdir там только псевдоним ).

обе реализации возвращают ноль при успехе и -1 при ошибке. Как вы можете видеть в manpage, более различающиеся значения errno возможны в варианте POSIX, но это не должно иметь значения для большинства случаев использования.


Для C++, boost:: filesystem:: current_path (прототипы сеттера и геттера).

библиотека файловой системы на основе Boost.Файловая система будет добавлен в стандарт.


тут chdir() делать то, что вы хотите? Он работает как под POSIX, так и под Windows.


этот кросс-платформенный пример кода для изменения рабочего каталога с помощью POSIX chdir и MS _chdir как рекомендуют в ответ. Аналогично для определения текущего рабочего каталога, аналогичный getcwd и _getcwd есть.

эти различия платформы скрыты за макросами cd и cwd.

согласно документации, chdir'подпись S составляет int chdir(const char *path) здесь path is абсолютный или относительный. chdir вернет 0 при успехе. getcwd немного сложнее, потому что ему нужен (в одном варианте) буфер для хранения извлеченного пути, как показано в char *getcwd(char *buf, size_t size). Он возвращает NULL при сбое и указатель на тот же переданный буфер при успехе. Образец кода использует этот возвращенный указатель char напрямую.

образец основан на @MarcD, но исправляет утечку памяти. Кроме того, я стремился к сжатию, без зависимостей и только к основному сбою/ошибке проверка, а также обеспечение его работы на нескольких (общих) платформах.

Я тестировал его на OSX 10.11.6, Centos7 и Win10. Для OSX & Centos я использовал g++ changedir.cpp -o changedir построить и запустить как ./changedir <path>.

на Win10, я построил с cl.exe changedir.cpp /EHsc /nologo.

решение 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;
}

OSX листинг:

$ g++ changedir.c-o changedir
$ ./испытания changedir
CWD:/пользователи / Phil
CWD изменен на:/Users/Phil / testing

Centos Листинг:

$ g++ changedir.c-o changedir
$ ./changedir
Каталог не предоставляется
$ ./does_not_exist changedir
CWD:/главная / Фил
$ ./ changedir Music
CWD:/главная / Фил
CWD изменено на: / home/phil / Music
$ ./changedir /
CWD:/главная / Фил
CWD изменен на: /

Win10 Листинг

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

c:\Users\Phil > changedir.ехе тест
CWD: c:\Users\Phil
CWD изменен на: c:\Users\Phil\test

Примечание: OSX использует clang и Centos gnu gcc за g++.


вы хотите chdir(2). Если вы пытаетесь заставить свою программу изменить рабочий каталог вашей оболочки - вы не можете. Есть много ответов на SO, уже решающих эту проблему.


вы имели в виду C или C++? Это совершенно разные языки.

в C стандарт, определяющий язык, не охватывает каталоги. Многие платформы, поддерживающие каталоги, имеют chdir функция, которая принимает char* или const char* аргумент, но даже там, где он существует, заголовок, где он объявлен, не является стандартным. Также могут быть тонкости относительно того, что означает аргумент (например, Windows имеет каталоги на диске).

в C++ поиск в интернете приводит к chdir и _chdir, и предполагает, что Boost не имеет интерфейса для chdir. Но я не буду комментировать дальше, так как я не знаю C++.


Не могу поверить, что никто еще не претендовал на награду за это!!!

вот кросс-платформенная реализация, которая получает и изменяет текущий рабочий каталог с помощью C++. Все, что требуется, это немного магии макросов, чтобы прочитать значение argv[0] и определить несколько небольших функций.

вот код для изменения каталогов в расположение исполняемого файла, который выполняется в настоящее время. Его можно легко адаптировать для изменения текущего рабочего каталога на любой каталог вы хотите.

код :

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

выход :

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

текущий рабочий каталог : c:\Windows Изменение каталога... Текущий рабочий каталог теперь : c:\ctwoplus\progcode\test\CWD

c:\Windows>


хороший кросс-платформенный способ изменить текущий каталог на C++ был предложен давно @pepper_chico. Это решение использует boost::filesystem::current_path().

для получения текущего рабочего каталога используйте:

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

для установки текущего рабочего каталога используйте:

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

Ниже приведены автономные вспомогательные функции:

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

вот мой полный пример кода о том, как установить / получить текущую работу каталог:

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

если boost установленный в вашей системе вы можете использовать следующую команду для компиляции этого образца:

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