Как я могу изменить текущую рабочую директорию на С++ агентом-агностиком?
Я нашел заголовочный файл direct.h
, совместимый с Windows, и unistd.h
, совместимый с UNIX/POSIX.
Как я могу изменить текущую рабочую директорию на С++ агентом-агностиком?
Я нашел заголовочный файл direct.h
, совместимый с Windows, и unistd.h
, совместимый с UNIX/POSIX.
Функция chdir
работает как на POSIX (manpage), так и на Windows (называется _chdir
, но существует псевдоним chdir
).
Обе реализации возвращают нуль при успехе и -1 при ошибке. Как видно из man-страницы, в POSIX-варианте возможны более выдающиеся значения errno, но это не должно действительно иметь значения для большинства случаев использования.
Для С++ boost:: filesystem:: current_path (прототипы прототипов и геттеров).
В стандарт будет добавлена библиотека файловой системы на основе Boost.Filesystem .
Выполняет ли chdir()
то, что вы хотите? Он работает как в POSIX, так и в Windows.
Этот кросс-платформенный пример кода для изменения рабочего каталога с использованием 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
.
$ 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;
}
$ g++ changeir.c -o changeir
тестирование
CWD:/Пользователи/Фил
CWD изменен на:/Пользователи/Фил/тестирование
$ 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 изменен на:/
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++
.
Вы хотите chdir(2)
. Если вы пытаетесь изменить свою рабочую директорию вашей программы, вы не можете. На SO уже много ответов, которые уже решают эту проблему.
Вы имели в виду C или С++? Это совершенно разные языки.
В C стандарт, который определяет язык, не охватывает каталоги. Многие платформы, поддерживающие каталоги, имеют функцию chdir
, которая принимает аргумент char*
или const char*
, но даже там, где он существует, заголовок, где он был объявлен, не является стандартным. Также могут быть тонкости относительно того, что означает аргумент (например, Windows имеет каталоги на каждом диске).
В С++ поиск в google приводит к chdir
и _chdir
, и предполагает, что Boost не имеет интерфейса для chdir. Но я больше не буду комментировать, потому что я не знаю С++.
Хороший кросс-платформенный способ сменить текущий каталог на С++ был предложен давным-давно @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
Не могу поверить, что никто не претендовал на награду на этом еще!
Вот кросс-платформенная реализация, которая получает и изменяет текущую рабочую директорию с помощью С++. Все, что требуется, - это малая магия, чтобы прочитать значение 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 >
Теперь с С++ 17 можно использовать std::filesystem::current_path
:
#include <filesystem>
int main() {
auto path = std::filesystem::current_path(); //getting path
std::filesystem::current_path(path); //setting path
}