web-dev-qa-db-ja.com

C ++で現在の作業ディレクトリを変更する

プラットフォームに依存しない方法でC++の現在の作業ディレクトリを変更するにはどうすればよいですか?

direct.hヘッダーファイルはWindows互換で、unistd.h、これはUNIX/POSIX互換です。

42
sparkFinder

chdir関数はPOSIX( manpage )とWindows( _chdir がありますが、エイリアスchdirは存在します)。

どちらの実装も成功時にゼロを返し、エラー時に-1を返します。マンページで見ることができるように、POSIXバリアントではより明確なerrno値が可能ですが、ほとんどのユースケースでは実際には違いはありません。

47
AndiDog

C++の場合、 boost :: filesystem :: current_path (setterおよびgetterプロトタイプ)。

Boost.Filesystemに基づくファイルシステムライブラリ 標準に追加されます

15
pepper_chico

chdir()はあなたが望むことをしますか? POSIXとWindowsの両方で動作します。

8
Jeremy Friesner

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でビルドしました。

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:/ Users/Phil
CWDの変更:/ Users/Phil/testing

Centosリスト:

$ 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の変更:/

Win10リスト

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

c:\ Users\Phil> changedir.exeテスト
CWD:c:\ Users\Phil
CWDはc:\ Users\Phil\testに変更されました

注:OSXはclangとCentos gnu gccg++の後ろで使用します。

8
Phil

chdir(2) が必要です。プログラムでシェルの作業ディレクトリを変更しようとしている場合、できません。 SOはすでにその問題に対処しています。

5
Carl Norum

CまたはC++のことですか?それらは完全に異なる言語です。

Cでは、言語を定義する標準はディレクトリをカバーしません。ディレクトリをサポートする多くのプラットフォームには、char*またはconst char*引数を取るchdir関数がありますが、宣言されているヘッダーが存在する場合でも標準ではありません。引数の意味についても微妙な点があるかもしれません(たとえば、Windowsにはドライブごとのディレクトリがあります)。

C++では、グーグルはchdir_chdirにつながり、Boostにはchdirへのインターフェースがないことを示唆しています。しかし、C++を知らないので、これ以上コメントしません。

5
Gilles

@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
3
Nikita

まだ誰もこの賞金を獲得したとは信じられません!!!

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>

2
MarcD

現在、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
}
1
João Paulo