如何获取程序运行的目录?

发布于 2024-07-06 10:41:19 字数 170 浏览 7 评论 0原文

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

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

Is there a platform-agnostic and filesystem-agnostic method to obtain the full path of the directory from where a program is running using C/C++? Not to be confused with the current working directory. (Please don't suggest libraries unless they're standard ones like clib or STL.)

(If there's no platform/filesystem-agnostic method, suggestions that work in Windows and Linux for specific filesystems are welcome too.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(24

前事休说 2024-07-13 10:41:19

以下是获取执行应用程序的完整路径的代码:

变量声明:

char pBuf[256];
size_t len = sizeof(pBuf); 

Windows:

int bytes = GetModuleFileName(NULL, pBuf, len);
return bytes ? bytes : -1;

Linux:

int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if(bytes >= 0)
    pBuf[bytes] = '\0';
return bytes;

Here's code to get the full path to the executing app:

Variable declarations:

char pBuf[256];
size_t len = sizeof(pBuf); 

Windows:

int bytes = GetModuleFileName(NULL, pBuf, len);
return bytes ? bytes : -1;

Linux:

int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if(bytes >= 0)
    pBuf[bytes] = '\0';
return bytes;
淡莣 2024-07-13 10:41:19

如果您在程序首次启动时获取当前目录,那么您实际上就拥有了程序启动的目录。 将值存储在变量中并稍后在程序中引用它。 这与保存当前可执行程序文件的目录不同。 它不一定是同一个目录; 如果有人从命令提示符运行该程序,则即使该程序文件位于其他位置,该程序也会从命令提示符的当前工作目录运行。

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);

If you fetch the current directory when your program first starts, then you effectively have the directory your program was started from. Store the value in a variable and refer to it later in your program. This is distinct from the directory that holds the current executable program file. It isn't necessarily the same directory; if someone runs the program from a command prompt, then the program is being run from the command prompt's current working directory even though the program file lives elsewhere.

getcwd is a POSIX function and supported out of the box by all POSIX compliant platforms. You would not have to do anything special (apart from incliding the right headers unistd.h on Unix and direct.h on windows).

Since you are creating a C program it will link with the default c run time library which is linked to by ALL processes in the system (specially crafted exceptions avoided) and it will include this function by default. The CRT is never considered an external library because that provides the basic standard compliant interface to the OS.

On windows getcwd function has been deprecated in favour of _getcwd. I think you could use it in this fashion.

#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);
乞讨 2024-07-13 10:41:19

这是来自 cplusplus 论坛

在 Windows 上:

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

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

在 Linux 上:< /strong>

#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 );
}

This is from the cplusplus forum

On windows:

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

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

On 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 );
}

On 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 );
}
指尖微凉心微凉 2024-07-13 10:41:19

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

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

恕我直言,这是您能得到的最接近的,具有良好的业力(Boost 是一套完善的高质量库)

If you want a standard way without libraries: No. The whole concept of a directory is not included in the standard.

If you agree that some (portable) dependency on a near-standard lib is okay: Use Boost's filesystem library and ask for the initial_path().

IMHO that's as close as you can get, with good karma (Boost is a well-established high quality set of libraries)

我的黑色迷你裙 2024-07-13 10:41:19

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

我认为这应该有效,但尚未测试,因此如果有效,请发表评论,如果无效,请修复。

I know it is very late at the day to throw an answer at this one but I found that none of the answers were as useful to me as my own solution. A very simple way to get the path from your CWD to your bin folder is like this:

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

You can now just use this as a base for your relative path. So for example I have this directory structure:

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

and I want to compile my source code to bin and write a log to test I can just add this line to my code.

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

I have tried this approach on Linux using full path, alias etc. and it works just fine.

NOTE:

If you are on windows you should use a '\' as the file separator not '/'. You will have to escape this too for example:

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

I think this should work but haven't tested, so comment would be appreciated if it works or a fix if not.

葬﹪忆之殇 2024-07-13 10:41:19

文件系统 TS 现在是一个标准(并受 gcc 5.3+ 和 clang 支持3.9+ ),因此您可以使用 current_path()< /a> 函数:

std::string path = std::experimental::filesystem::current_path();

在 gcc (5.3+) 中要包含文件系统,您需要使用:

#include <experimental/filesystem>

并使用 -lstdc++fs 标志链接您的代码。

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

Filesystem TS is now a standard ( and supported by gcc 5.3+ and clang 3.9+ ), so you can use current_path() function from it:

std::string path = std::experimental::filesystem::current_path();

In gcc (5.3+) to include Filesystem you need to use:

#include <experimental/filesystem>

and link your code with -lstdc++fs flag.

If you want to use Filesystem with Microsoft Visual Studio, then read this.

素罗衫 2024-07-13 10:41:19

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

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

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

No, there's no standard way. I believe that the C/C++ standards don't even consider the existence of directories (or other file system organizations).

On Windows the GetModuleFileName() will return the full path to the executable file of the current process when the hModule parameter is set to NULL. I can't help with Linux.

Also you should clarify whether you want the current directory or the directory that the program image/executable resides. As it stands your question is a little ambiguous on this point.

计㈡愣 2024-07-13 10:41:19

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

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

On Windows the simplest way is to use the _get_pgmptr function in stdlib.h to get a pointer to a string which represents the absolute path to the executable, including the executables name.

char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
書生途 2024-07-13 10:41:19

也许将当前工作目录与 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
/home/jeremy/Desktop/./test

Maybe concatenate the current working directory with argv[0]? I'm not sure if that would work in Windows but it works in linux.

For example:

#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;
}

When run, it outputs:

jeremy@jeremy-desktop:~/Desktop$ ./test
/home/jeremy/Desktop/./test

圈圈圆圆圈圈 2024-07-13 10:41:19

对于 Win32 GetCurrentDirectory 应该可以解决问题。

For Win32 GetCurrentDirectory should do the trick.

酒儿 2024-07-13 10:41:19

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

另请注意,当前目录和包含可执行文件的目录是两个不同的东西,因此 getcwd() 也不会帮助您。

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

You can not use argv[0] for that purpose, usually it does contain full path to the executable, but not nessesarily - process could be created with arbitrary value in the field.

Also mind you, the current directory and the directory with the executable are two different things, so getcwd() won't help you either.

On Windows use GetModuleFileName(), on Linux read /dev/proc/procID/.. files.

海风掠过北极光 2024-07-13 10:41:19

只是我的两分钱,但以下代码不能在 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 已经存在很多年了。

Just my two cents, but doesn't the following code portably work in 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';
}

Seems to work for me on Linux at least.

Based on the previous idea, I now have:

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

With implementation:

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;
}

And initialization trick in main():

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

Thanks @Sam Redway for the argv[0] idea. And of course, I understand that C++17 was not around for many years when the OP asked the question.

顾挽 2024-07-13 10:41:19

只是在这里迟来的堆砌,...

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

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

Just to belatedly pile on here,...

there is no standard solution, because the languages are agnostic of underlying file systems, so as others have said, the concept of a directory based file system is outside the scope of the c / c++ languages.

on top of that, you want not the current working directory, but the directory the program is running in, which must take into account how the program got to where it is - ie was it spawned as a new process via a fork, etc. To get the directory a program is running in, as the solutions have demonstrated, requires that you get that information from the process control structures of the operating system in question, which is the only authority on this question. Thus, by definition, its an OS specific solution.

似狗非友 2024-07-13 10:41:19
#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);
}
#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);
}
日暮斜阳 2024-07-13 10:41:19

从 C++11 开始,使用实验文件系统,以及 C++14-C++17 以及使用官方文件系统。

应用程序.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();

应用程序.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
}

Works with starting from C++11, using experimental filesystem, and C++14-C++17 as well using official filesystem.

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
}
回忆躺在深渊里 2024-07-13 10:41:19

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

示例:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}

For Windows system at console you can use system(dir) command. And console gives you information about directory and etc. Read about the dir command at cmd. But for Unix-like systems, I don't know... If this command is run, read bash command. ls does not display directory...

Example:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}
つ可否回来 2024-07-13 10:41:19

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

假设你有这样的路径:

"path/to/file/folder"

出于某种原因,在 eclipse 中制作的 Linux 构建的可执行文件可以很好地工作。 然而,如果给定这样的路径,Windows 会变得非常困惑!

如上所述,有多种方法可以获取可执行文件的当前路径,但我发现在大多数情况下最有效的方法是将其附加到路径的前面:

"./path/to/file/folder"

只需添加“./”即可排序! :) 然后你可以从任何你想要的目录开始加载,只要它是可执行文件本身。

编辑:如果您尝试从 code::blocks 启动可执行文件(如果这是正在使用的开发环境),则这将不起作用,由于某种原因,code::blocks 无法正确加载内容... :D

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

"resources/Example.data"

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

For relative paths, here's what I did. I am aware of the age of this question, I simply want to contribute a simpler answer that works in the majority of cases:

Say you have a path like this:

"path/to/file/folder"

For some reason, Linux-built executables made in eclipse work fine with this. However, windows gets very confused if given a path like this to work with!

As stated above there are several ways to get the current path to the executable, but the easiest way I find works a charm in the majority of cases is appending this to the FRONT of your path:

"./path/to/file/folder"

Just adding "./" should get you sorted! :) Then you can start loading from whatever directory you wish, so long as it is with the executable itself.

EDIT: This won't work if you try to launch the executable from code::blocks if that's the development environment being used, as for some reason, code::blocks doesn't load stuff right... :D

EDIT2: Some new things I have found is that if you specify a static path like this one in your code (Assuming Example.data is something you need to load):

"resources/Example.data"

If you then launch your app from the actual directory (or in Windows, you make a shortcut, and set the working dir to your app dir) then it will work like that.
Keep this in mind when debugging issues related to missing resource/file paths. (Especially in IDEs that set the wrong working dir when launching a build exe from the IDE)

一抹淡然 2024-07-13 10:41:19

一个库解决方案(尽管我知道这没有被要求)。
如果你碰巧使用 Qt:
QCoreApplication::applicationDirPath()

A library solution (although I know this was not asked for).
If you happen to use Qt:
QCoreApplication::applicationDirPath()

祁梦 2024-07-13 10:41:19

当前 .exe 的路径


#include <Windows.h>

std::wstring getexepathW()
{
    wchar_t result[MAX_PATH];
    return std::wstring(result, GetModuleFileNameW(NULL, result, MAX_PATH));
}

std::wcout << getexepathW() << std::endl;

//  -------- OR --------

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

std::cout << getexepathA() << std::endl;

Path to the current .exe


#include <Windows.h>

std::wstring getexepathW()
{
    wchar_t result[MAX_PATH];
    return std::wstring(result, GetModuleFileNameW(NULL, result, MAX_PATH));
}

std::wcout << getexepathW() << std::endl;

//  -------- OR --------

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

std::cout << getexepathA() << std::endl;

柠檬色的秋千 2024-07-13 10:41:19

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

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

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

On POSIX platforms, you can use getcwd().

On Windows, you may use _getcwd(), as use of getcwd() has been deprecated.

For standard libraries, if Boost were standard enough for you, I would have suggested Boost::filesystem, but they seem to have removed path normalization from the proposal. You may have to wait until TR2 becomes readily available for a fully standard solution.

始于初秋 2024-07-13 10:41:19

Boost Filesystem 的 initial_path() 的行为类似于 POSIX 的 getcwd(),本身也不会满足您的要求,但将 argv[0] 附加到其中之一他们中的一些人应该这样做。

您可能会注意到结果并不总是漂亮 - 您可能会得到类似 /foo/bar/../../baz/a.out/foo/bar// 的内容baz/a.out,但我相信它总是会产生一个命名可执行文件的有效路径(请注意,路径中的连续斜杠会折叠为一个)。

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

Boost Filesystem's initial_path() behaves like POSIX's getcwd(), and neither does what you want by itself, but appending argv[0] to either of them should do it.

You may note that the result is not always pretty--you may get things like /foo/bar/../../baz/a.out or /foo/bar//baz/a.out, but I believe that it always results in a valid path which names the executable (note that consecutive slashes in a path are collapsed to one).

I previously wrote a solution using envp (the third argument to main() which worked on Linux but didn't seem workable on Windows, so I'm essentially recommending the same solution as someone else did previously, but with the additional explanation of why it is actually correct even if the results are not pretty.

梦初启 2024-07-13 10:41:19

正如 Minok 提到的,C 标准或 C++ 标准中没有指定此类功能。 这被认为是纯粹特定于操作系统的功能,例如在 POSIX 标准中指定。

Thorsten79给出了很好的建议,那就是Boost.Filesystem库。 但是,如果您不希望程序有任何二进制形式的链接时依赖项,这可能会很不方便。

我推荐的一个不错的选择是收集 100% 仅包含标头的 STLSoft C++ 库 Matthew Wilson(有关 C++ 的必读书籍的作者)。 有可移植的外观 PlatformSTL 可以访问系统特定的 API:Windows 上的 WinSTL 和 Unix 上的 UnixSTL,因此它是可移植的解决方案。 所有特定于系统的元素都是使用特征和策略来指定的,因此它是可扩展的框架。 当然,提供了文件系统库。

As Minok mentioned, there is no such functionality specified ini C standard or C++ standard. This is considered to be purely OS-specific feature and it is specified in POSIX standard, for example.

Thorsten79 has given good suggestion, it is Boost.Filesystem library. However, it may be inconvenient in case you don't want to have any link-time dependencies in binary form for your program.

A good alternative I would recommend is collection of 100% headers-only STLSoft C++ Libraries Matthew Wilson (author of must-read books about C++). There is portable facade PlatformSTL gives access to system-specific API: WinSTL for Windows and UnixSTL on Unix, so it is portable solution. All the system-specific elements are specified with use of traits and policies, so it is extensible framework. There is filesystem library provided, of course.

烟沫凡尘 2024-07-13 10:41:19

Linux bash 命令
哪个程序名将报告程序的路径。

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

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

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

The linux bash command
which progname will report a path to program.

Even if one could issue the which command from within your program and direct the output to a tmp file and the program
subsequently reads that tmp file, it will not tell you if that program is the one executing. It only tells you where a program having that name is located.

What is required is to obtain your process id number, and to parse out the path to the name

In my program I want to know if the program was
executed from the user's bin directory or from another in the path
or from /usr/bin. /usr/bin would contain the supported version.
My feeling is that in Linux there is the one solution that is portable.

灯角 2024-07-13 10:41:19

以下内容在 macOS 10.15.7

brew install boost

main.cpp

#include <iostream>
#include <boost/filesystem.hpp>

int main(int argc, char* argv[]){
  boost::filesystem::path p{argv[0]};
  p = absolute(p).parent_path();
  std::cout << p << std::endl;
  return 0;
}

编译上对我来说效果很好

g++ -Wall -std=c++11 -l boost_filesystem main.cpp

The following worked well for me on macOS 10.15.7

brew install boost

main.cpp

#include <iostream>
#include <boost/filesystem.hpp>

int main(int argc, char* argv[]){
  boost::filesystem::path p{argv[0]};
  p = absolute(p).parent_path();
  std::cout << p << std::endl;
  return 0;
}

Compiling

g++ -Wall -std=c++11 -l boost_filesystem main.cpp
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文