filesystem - 用C++更改當前工作目錄




c++ set path (6)

如何以平台無關的方式在C ++中更改當前的工作目錄?

我發現了direct.h Windows兼容的direct.h頭文件和與UNIX / POSIX兼容的unistd.h


chdir()能做你想做的嗎? 它適用於POSIX和Windows。


chdir函數適用於POSIX(手冊manpage )和Windows( _chdir那裡稱為_chdir ,但存在別名chdir )。

兩個實現在成功時返回零,在出錯時返回-1。 正如您在聯機幫助頁中所看到的,POSIX變體中可能存在更多不同的errno值,但對於大多數用例而言,這不應該有所不同。


你想要chdir(2) 。 如果您嘗試讓程序更改shell的工作目錄 - 則不能。 SO上有很多答案已經解決了這個問題。


你的意思是C還是C ++? 它們是完全不同的語言。

在C中,定義語言的標準不包括目錄。 許多支持目錄的平台都有一個chdir函數,它接受一個char*const char*參數,但即使它存在,它所聲明的標題也不是標準的。 關於參數意味著什麼(例如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

這個跨平台的示例代碼,用於在本回答中使用POSIX chdir和MS _chdir更改工作目錄。 同樣,為了確定當前工作目錄,使用類似的getcwd_getcwd

這些平台差異隱藏在宏cdcwd

根據文檔, chdir的簽名是int chdir(const char *path) ,其中path是絕對path或相對pathchdir將在成功時返回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音樂
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 test
CWD:c:\ Users \ Phil
CWD更改為:c:\ Users \ Phil \ test

注意:OSX在g++後面使用了clang和Centos gnu gcc







working-directory