プラットフォームに依存しない方法でC++の現在の作業ディレクトリを変更するにはどうすればよいですか?
direct.h
ヘッダーファイルはWindows互換で、unistd.h
、これはUNIX/POSIX互換です。
C++の場合、 boost :: filesystem :: current_path (setterおよびgetterプロトタイプ)。
Boost.Filesystemに基づくファイルシステムライブラリ 標準に追加されます 。
chdir()
はあなたが望むことをしますか? POSIXとWindowsの両方で動作します。
this answer で推奨されている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を返し、成功すると同じ渡されたバッファへのポインタを返します。コードサンプルは、返されたこのcharポインターを直接使用します。
サンプルは@MarcDに基づいていますが、メモリリークを修正します。さらに、簡潔で、依存関係はなく、基本的な障害/エラーチェックだけでなく、複数の(共通の)プラットフォームで動作することを確認しました。
OSX 10.11.6、Centos7、およびWin10でテストしました。 OSXとCentosでは、g++ changedir.cpp -o changedir
を使用してビルドし、./changedir <path>
として実行しました。
Win10では、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 ++ changedir.c -o changedir
$ ./changedirテスト
CWD:/ Users/Phil
CWDの変更:/ Users/Phil/testing
$ g ++ changedir.c -o changedir
$ ./changedir
ディレクトリが提供されていません
$ ./changedir does_not_exist
CWD:/ home/phil
$ ./changedir Music
CWD:/ home/phil
CWDの変更:/ home/phil/Music
$ ./changedir /
CWD:/ home/phil
CWDの変更:/
cl.exe changedir.cpp/EHsc/nologo
changedir.cppc:\ Users\Phil> changedir.exeテスト
CWD:c:\ Users\Phil
CWDはc:\ Users\Phil\testに変更されました
注:OSXはclang
とCentos gnu gcc
をg++
の後ろで使用します。
chdir(2)
が必要です。プログラムでシェルの作業ディレクトリを変更しようとしている場合、できません。 SOはすでにその問題に対処しています。
CまたはC++のことですか?それらは完全に異なる言語です。
Cでは、言語を定義する標準はディレクトリをカバーしません。ディレクトリをサポートする多くのプラットフォームには、char*
またはconst char*
引数を取るchdir
関数がありますが、宣言されているヘッダーが存在する場合でも標準ではありません。引数の意味についても微妙な点があるかもしれません(たとえば、Windowsにはドライブごとのディレクトリがあります)。
C++では、グーグルはchdir
と_chdir
につながり、Boostにはchdirへのインターフェースがないことを示唆しています。しかし、C++を知らないので、これ以上コメントしません。
@pepper_chicoは、C++で現在のディレクトリを変更するクロスプラットフォームの素敵な方法がかなり前に提案されました。このソリューションでは 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
まだ誰もこの賞金を獲得したとは信じられません!!!
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++ 17では std::filesystem::current_path
:
#include <filesystem>
int main() {
auto path = std::filesystem::current_path(); //getting path
std::filesystem::current_path(path); //setting path
}