是否有一种平台不可知和文件系统不可知的方法来获取程序运行的目录的完整路径?不要与当前工作目录混淆。(请不要推荐库,除非它们是像clib或STL这样的标准库。)

(如果没有平台/文件系统不可知的方法,也欢迎在Windows和Linux中针对特定文件系统工作的建议。)


当前回答

linux bash命令 哪个progname将报告程序的路径。

即使可以在程序中发出which命令,并将输出定向到tmp文件和程序 随后读取TMP文件,它不会告诉您该程序是否是正在执行的程序。它只告诉您具有此名称的程序位于何处。

所需要的是获取进程id号,并解析出该名称的路径

在我的程序中,我想知道程序是否 从用户的bin目录或路径中的其他目录执行 或者从/usr/bin。/usr/bin将包含受支持的版本。 我的感觉是在Linux中有一个可移植的解决方案。

其他回答

从c++ 11开始,使用实验文件系统,c++ 14- c++ 17以及使用正式文件系统。

application.h:

#pragma once

//
// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
//
#ifdef __cpp_lib_filesystem
#include <filesystem>
#else
#include <experimental/filesystem>

namespace std {
    namespace filesystem = experimental::filesystem;
}
#endif

std::filesystem::path getexepath();

application.cpp:

#include "application.h"
#ifdef _WIN32
#include <windows.h>    //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h>     //readlink
#endif

std::filesystem::path getexepath()
{
#ifdef _WIN32
    wchar_t path[MAX_PATH] = { 0 };
    GetModuleFileNameW(NULL, path, MAX_PATH);
    return path;
#else
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
#endif
}

我知道现在回答这个问题已经很晚了,但我发现没有一个答案像我自己的解决方案那样对我有用。一个非常简单的方法来获取路径从你的CWD到你的bin文件夹是这样的:

int main(int argc, char* argv[])
{
    std::string argv_str(argv[0]);
    std::string base = argv_str.substr(0, argv_str.find_last_of("/"));
}

您现在可以使用它作为相对路径的基。例如,我有这样的目录结构:

main
  ----> test
  ----> src
  ----> bin

我想把我的源代码编译到bin并写一个日志来测试,我可以把这一行添加到我的代码中。

std::string pathToWrite = base + "/../test/test.log";

我在Linux上尝试过这种方法,使用全路径,别名等,它工作得很好。

注意:

如果你是在windows中,你应该使用“\”作为文件分隔符,而不是“/”。你也需要转义这个,例如:

std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));

我认为这应该工作,但还没有测试,所以评论将是感激如果它工作或修复如果不是。

对于Win32, GetCurrentDirectory应该做到这一点。

只是我的两美分,但下面的代码在c++ 17中不能移植吗?

#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main(int argc, char* argv[])
{
    std::cout << "Path is " << fs::path(argv[0]).parent_path() << '\n';
}

至少在Linux上对我有用。

根据前面的想法,我现在有:

std::filesystem::path prepend_exe_path(const std::string& filename, const std::string& exe_path = "");

与实现:

fs::path prepend_exe_path(const std::string& filename, const std::string& exe_path)
{
    static auto exe_parent_path = fs::path(exe_path).parent_path();
    return exe_parent_path / filename;
}

main()中的初始化技巧:

(void) prepend_exe_path("", argv[0]);

感谢@Sam Redway的argv[0]想法。当然,我知道当OP提出这个问题时,c++ 17还没有出现很多年。

你不能为此目的使用argv[0],通常它包含可执行文件的完整路径,但也不是必须的——进程可以在字段中使用任意值创建。

还要注意,当前目录和可执行文件所在的目录是两个不同的东西,所以getcwd()也帮不了你。

Windows上使用GetModuleFileName(), Linux上读取/dev/proc/procID/..文件。