是否存在与平台无关且与文件系统无关的方法来获取使用C / C ++运行程序的目录的完整路径?不要与当前的工作目录混淆。 (请不要建议使用库,除非它们是clib或STL等标准库。)

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

有帮助吗?

解决方案

这是获取正在执行的应用程序的完整路径的代码:

视窗:

int bytes = GetModuleFileName(NULL, pBuf, len);
if(bytes == 0)
    return -1;
else
    return bytes;

Linux的:

char szTmp[32];
sprintf(szTmp, "/proc/%d/exe", getpid());
int bytes = MIN(readlink(szTmp, pBuf, len), len - 1);
if(bytes >= 0)
    pBuf[bytes] = '\0';
return bytes;

其他提示

如果在程序首次启动时获取当前目录,则可以有效地获取程序启动目录。将值存储在变量中,稍后在程序中引用它。这与包含当前可执行程序文件的目录不同。它不一定是同一个目录;如果有人从命令提示符运行程序,那么程序正在命令提示符的当前工作目录运行,即使程序文件位于其他地方。

getcwd是一个POSIX功能,并且所有POSIX兼容平台都支持开箱即用。你不需要做任何特别的事情(除了在Unix上将unistd.h和在windows上的direct.h合并到正确的头文件中)。

由于您正在创建一个C程序,它将链接到默认的c运行时库,该库由系统中的所有进程链接(避免特制的异常),默认情况下它将包含此函数。 CRT从不被视为外部库,因为它为操作系统提供了基本的标准兼容接口。

在Windows上,getcwd函数已被弃用,转而使用_getcwd。我想你可以这种方式使用它。

#include <stdio.h>  /* defines FILENAME_MAX */
#ifdef WINDOWS
    #include <direct.h>
    #define GetCurrentDir _getcwd
#else
    #include <unistd.h>
    #define GetCurrentDir getcwd
 #endif

 char cCurrentPath[FILENAME_MAX];

 if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
     {
     return errno;
     }

cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */

printf ("The current working directory is %s", cCurrentPath);

这是来自 cplusplus论坛

在Windows上:

#include <string>
#include <windows.h>

std::string getexepath()
{
  char result[ MAX_PATH ];
  return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
}

在Linux上:

#include <string>
#include <limits.h>
#include <unistd.h>

std::string getexepath()
{
  char result[ PATH_MAX ];
  ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
  return std::string( result, (count > 0) ? count : 0 );
}

在HP-UX上:

#include <string>
#include <limits.h>
#define _PSTAT64
#include <sys/pstat.h>
#include <sys/types.h>
#include <unistd.h>

std::string getexepath()
{
  char result[ PATH_MAX ];
  struct pst_status ps;

  if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0)
    return std::string();

  if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0)
    return std::string();

  return std::string( result );
}

如果你想要一种没有库的标准方式:不。目录的整个概念不包含在标准中。

如果您同意对近标准库的某些(可移植)依赖是可以的:使用 Boost的文件系统库并要求 initial_path()

恕我直言,尽可能接近,有良好的业力(Boost是一套完善的高质量图书馆)

Filesystem TS 现已成为标准(并受gcc 5.3支持) +和clang 3.9+),所以你可以使用 current_path() 从中起作用:

在gcc(5.3+)中包含你需要使用的Filesystem:

#include <experimental/filesystem>

并将您的代码与 -lstdc ++ fs 标志链接。

如果要将文件系统与Microsoft Visual Studio一起使用,请阅读本文

我知道现在很晚才回答这个问题,但我发现没有一个答案对我来说和我自己的解决方案一样有用。获取从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("\\"));

我认为这应该有效,但尚未经过测试,因此如果有效,则表示赞赏,如果没有,则表示感谢。

不,没有标准的方法。我相信C / C ++标准甚至不考虑目录(或其他文件系统组织)的存在。

在Windows上,当 hModule 参数设置为 NULL GetModuleFileName()将返回当前进程的可执行文件的完整路径>。我无法帮助Linux。

此外,您应该澄清您是否需要当前目录或程序映像/可执行文件所在的目录。就目前而言,你的问题在这一点上有点含糊不清。

也许将当前工作目录与argv [0]连接起来?我不确定它是否适用于Windows,但它适用于Linux。

例如:

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char **argv) {
    char the_path[256];

    getcwd(the_path, 255);
    strcat(the_path, "/");
    strcat(the_path, argv[0]);

    printf("%s\n", the_path);

    return 0;
}

运行时,输出:

   jeremy @ jeremy-desktop:〜/ Desktop $ ./test
  /家庭/杰里米/桌面/./测试

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

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

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

在Windows上,最简单的方法是使用 stdlib.h 中的 _get_pgmptr 函数来获取指向字符串的指针,该字符串表示可执行文件的绝对路径,包括可执行文件名称。

char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe

对于Win32 GetCurrentDirectory 应该做的伎俩

刚好迟到了,......

没有标准的解决方案,因为语言与底层文件系统无关,正如其他人所说的那样,基于目录的文件系统的概念超出了c / c ++语言的范围。

最重要的是,你不需要当前的工作目录,而是程序运行的目录,它必须考虑程序如何到达它的位置 - 即它是否通过fork生成为新进程要获得正在运行程序的目录,正如解决方案所示,要求您从相关操作系统的过程控制结构中获取该信息,这是此问题的唯一权限。因此,根据定义,它是一个特定于操作系统的解决方案。

对于Windows系统的控制台,您可以使用system( dir )命令。并且控制台为您提供有关目录等的信息。阅读 cmd 中的 dir 命令。但对于类Unix系统,我不知道......如果运行此命令,请阅读bash命令。 ls 不显示目录...

示例:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}
#include <windows.h>
using namespace std;

// The directory path returned by native GetCurrentDirectory() no end backslash
string getCurrentDirectoryOnWindows()
{
    const unsigned long maxDir = 260;
    char currentDir[maxDir];
    GetCurrentDirectory(maxDir, currentDir);
    return string(currentDir);
}

linux bash命令 哪个progname 会报告一个程序路径。

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

所需要的是获取您的进程ID号,并解析名称的路径

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

对于相对路径,这就是我所做的。我知道这个问题的年龄,我只想提供一个在大多数情况下有效的简单答案:

假设您有这样的路径:

"path/to/file/folder"

出于某种原因,在Eclipse中制作的Linux构建的可执行文件可以正常工作。但是,如果给出像这样的路径,windows会变得非常混乱!

如上所述,有几种方法可以获得可执行文件的当前路径,但在大多数情况下,我找到的最简单的方法是将其添加到路径的前面:

"./path/to/file/folder"

只需添加“./&”;应该让你排序! :)然后你就可以从你想要的任何目录开始加载,只要它与可执行文件本身一起。

编辑:如果您尝试从代码:: blocks启动可执行文件,如果这是正在使用的开发环境,这将无效,因为某些原因,code :: blocks不能正确加载...:D

EDIT2:我发现的一些新事物是,如果你在代码中指定一个像这样的静态路径(假设你需要加载Example.data):

"resources/Example.data"

如果您然后从实际目录启动您的应用程序(或在Windows中,您创建一个快捷方式,并将工作目录设置为您的应用程序目录),那么它将像这样工作。 在调试与缺少资源/文件路径相关的问题时,请记住这一点。 (特别是在从IDE启动构建exe时设置错误工作目录的IDE中)

在POSIX平台上,您可以使用 getcwd()

在Windows上,您可以使用 _getcwd(),使用 getcwd()已被弃用。

对于标准库,如果Boost足够标准,我会建议使用Boost :: filesystem,但它们似乎已从提案中删除了路径规范化。您可能需要等到 TR2随时可用获得完全标准的解决方案。

Boost Filesystem的 initial_path()的行为类似于POSIX的 getcwd(),既不是你想要的,也不是附加 argv [0] 他们中的任何一个都应该这样做。

你可能会注意到结果并不总是很好 - 你可能会得到像 / foo / bar /../../ baz / a.out / foo /这样的东西bar // baz / a.out ,但我相信它总是会产生一个命名可执行文件的有效路径(注意路径中的连续斜线折叠为一个)。

我之前使用 envp main()的第三个参数编写了一个解决方案,它在Linux上工作但在Windows上似乎不可行,所以我基本上推荐与之前其他人一样的解决方案,但附加解释为什么它实际上是正确的,即使结果不是很好。

如上所述 Minok ,在C标准或C ++标准中没有指定此类功能。这被认为是纯OS特有的功能,例如在POSIX标准中指定。

Thorsten79 给出了很好的建议,它是Boost.Filesystem库。但是,如果您不希望以二进制形式为程序提供任何链接时依赖性,则可能不方便。

我建议的一个很好的选择是100%标题的集合 STLSoft C ++库 Matthew Wilson (关于C ++的必读书籍的作者) 。有便携式外观PlatformSTL可以访问系统特定的API:Windows上的WinSTL和Unix上的UnixSTL,因此它是便携式解决方案。所有特定于系统的元素都使用特征和策略指定,因此它是可扩展的框架。当然还提供了文件系统库。

图书馆解决方案(虽然我知道没有要求)。 如果你碰巧使用Qt: <代码> QCoreApplication :: applicationDirPath()

stdlib.h 中使用 realpath(),如下所示:

char *working_dir_path = realpath(".", NULL);

从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
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top