Подтвердить что ты не робот

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

Как я могу изменить текущую рабочую директорию на С++ агентом-агностиком?

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

4b9b3361

Ответ 1

Функция chdir работает как на POSIX (manpage), так и на Windows (называется _chdir, но существует псевдоним chdir).

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

Ответ 2

Для С++ boost:: filesystem:: current_path (прототипы прототипов и геттеров).

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

Ответ 3

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

Ответ 4

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

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

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

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

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

На Win10 я cl.exe changedir.cpp/EHsc/nologo с cl.exe changedir.cpp/EHsc/nologo.

Решение MVP

$ cat changeir.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++ changeir.c -o changeir
тестирование
CWD:/Пользователи/Фил
CWD изменен на:/Пользователи/Фил/тестирование

Список Centos:

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

Win10 Listing

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

Тест c:\Users\Phil> changeir.exe
CWD: c:\Users\Phil
CWD изменено на: c:\Users\Phil\test

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

Ответ 5

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

Ответ 6

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

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

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

Ответ 7

Хороший кросс-платформенный способ сменить текущий каталог на С++ был предложен давным-давно @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" ) ));    

Bellow - это автономные вспомогательные функции:

#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

Ответ 8

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

Вот кросс-платформенная реализация, которая получает и изменяет текущую рабочую директорию с помощью С++. Все, что требуется, - это малая магия, чтобы прочитать значение 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\тест\УХО\cwd.exe

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

C:\Windows >

Ответ 9

Теперь с С++ 17 можно использовать std::filesystem::current_path:

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