是否存在与平台无关且与文件系统无关的方法来获取使用C / C ++运行程序的目录的完整路径?不要与当前的工作目录混淆。 (请不要建议使用库,除非它们是clib或STL等标准库。)
(如果没有平台/文件系统无关的方法,也欢迎在Windows和Linux中使用特定文件系统的建议。)
答案 0 :(得分:168)
这是获取正在执行的应用程序的完整路径的代码:
视窗:
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;
答案 1 :(得分:162)
如果在程序首次启动时获取当前目录,则可以有效地获取程序启动目录。将值存储在变量中,稍后在程序中引用它。这与the directory that holds the current executable program file不同。它不一定是同一个目录;如果有人从命令提示符运行程序,那么程序正在从命令提示符的当前工作目录运行,即使程序文件位于其他地方。
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);
答案 2 :(得分:36)
在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 );
}
答案 3 :(得分:28)
如果你想要一种没有库的标准方式:不。目录的整个概念不包含在标准中。
如果您同意对近标准库的某些(可移植)依赖是可以的:使用Boost's filesystem library并请求initial_path()。
恕我直言,尽可能接近,有良好的业力(Boost是一套完善的高质量图书馆)
答案 4 :(得分:17)
Filesystem TS is now a standard(并受gcc 5.3+和clang 3.9+支持),因此您可以使用current_path()
函数:
std::string path = std::experimental::filesystem::current_path();
在gcc(5.3+)中包含你需要使用的Filesystem:
#include <experimental/filesystem>
并将您的代码与-lstdc++fs
标记相关联。
如果要将文件系统与Microsoft Visual Studio一起使用,则read this。
答案 5 :(得分:17)
我知道现在很晚才回答这个问题,但我发现没有一个答案对我来说和我自己的解决方案一样有用。获取从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上,你应该使用&#39; \&#39;作为文件分隔符不是&#39; /&#39;。你也必须逃避这个例子:
std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));
我认为这应该有效,但尚未经过测试,因此如果有效,可以表示赞赏,如果没有,则表示感谢。
答案 6 :(得分:9)
不,没有标准的方法。我相信C / C ++标准甚至不考虑目录(或其他文件系统组织)的存在。
在Windows上,当 hModule 参数设置为 NULL GetModuleFileName()将返回当前进程的可执行文件的完整路径>。我无法帮助Linux。
此外,您应该澄清您是否需要当前目录或程序映像/可执行文件所在的目录。就目前而言,你的问题在这一点上有点含糊不清。
答案 7 :(得分:7)
也许将当前工作目录与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
/家庭/杰里米/桌面/./测试
答案 8 :(得分:6)
你不能为此目的使用argv [0],通常它确实包含可执行文件的完整路径,但不是必须的 - 可以在字段中使用任意值创建进程。
还要注意,当前目录和带有可执行文件的目录是两个不同的东西,所以getcwd()也不会帮助你。
在Windows上使用GetModuleFileName(),在Linux上读取/ dev / proc / procID / ..文件。
答案 9 :(得分:6)
在Windows上,最简单的方法是使用_get_pgmptr
中的stdlib.h
函数来获取指向字符串的指针,该字符串表示可执行文件的绝对路径,包括可执行文件名称。
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
答案 10 :(得分:5)
对于Win32 GetCurrentDirectory应该这样做。
答案 11 :(得分:3)
对于Windows系统的控制台,您可以使用system(dir
)命令。并且控制台为您提供有关目录等的信息。请阅读dir
处的cmd
命令。但对于类Unix系统,我不知道......如果运行此命令,请阅读bash命令。 ls
不显示目录...
示例:
int main()
{
system("dir");
system("pause"); //this wait for Enter-key-press;
return 0;
}
答案 12 :(得分:3)
刚好迟到了,......
没有标准的解决方案,因为语言与底层文件系统无关,正如其他人所说的那样,基于目录的文件系统的概念超出了c / c ++语言的范围。
最重要的是,你不需要当前的工作目录,而是程序运行的目录,它必须考虑程序如何到达它的位置 - 即它是否通过fork生成为新进程要获得正在运行程序的目录,正如解决方案所示,要求您从相关操作系统的过程控制结构中获取该信息,这是此问题的唯一权限。因此,根据定义,它是一个特定于操作系统的解决方案。
答案 13 :(得分:2)
#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);
}
答案 14 :(得分:1)
对于相对路径,这就是我所做的。我知道这个问题的年龄,我只想提供一个在大多数情况下有效的简单答案:
假设您有这样的路径:
"path/to/file/folder"
出于某种原因,在Eclipse中制作的Linux构建的可执行文件可以正常工作。但是,如果给出像这样的路径,windows会变得非常混乱!
如上所述,有几种方法可以获得可执行文件的当前路径,但在大多数情况下,我找到的最简单的方法是将其添加到路径的前面:
"./path/to/file/folder"
只需添加“./”即可让您排序! :)然后你就可以从你想要的任何目录开始加载,只要它与可执行文件本身一起。
编辑:如果您尝试从代码:: blocks启动可执行文件,如果这是正在使用的开发环境,这将无效,因为某些原因,code :: blocks不能正确加载...:DEDIT2:我发现的一些新事物是,如果你在代码中指定一个像这样的静态路径(假设你需要加载Example.data):
"resources/Example.data"
如果您然后从实际目录启动您的应用程序(或在Windows中,您创建一个快捷方式,并将工作目录设置为您的应用程序目录),那么它将像这样工作。 在调试与缺少资源/文件路径相关的问题时,请记住这一点。 (特别是在从IDE启动构建exe时设置错误工作目录的IDE中)
答案 15 :(得分:1)
linux bash命令 哪个progname 会报告一个程序路径。
即使可以从程序中发出which命令并将输出定向到tmp文件和程序 随后读取该tmp文件,它不会告诉您该程序是否正在执行。它只会告诉您具有该名称的程序所在的位置。
所需要的是获取您的进程ID号,并解析名称的路径
在我的课程中,我想知道该课程是否合适 从用户的bin目录或路径中的另一个目录执行 或来自/ usr / bin。 / usr / bin将包含受支持的版本。 我的感觉是在Linux中有一个可移植的解决方案。
答案 16 :(得分:1)
只需两美分,但以下代码在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已经存在了很多年。
答案 17 :(得分:1)
当前 .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;
答案 18 :(得分:0)
如上所述 Minok ,在C标准或C ++标准中没有指定此类功能。这被认为是纯OS特有的功能,例如在POSIX标准中指定。
Thorsten79 给出了很好的建议,它是Boost.Filesystem库。但是,如果您不希望以二进制形式为程序提供任何链接时依赖性,则可能不方便。
我建议的一个很好的选择是100%标题的集合STLSoft C++ Libraries Matthew Wilson(关于C ++的必读书籍的作者)。有便携式外观PlatformSTL可以访问系统特定的API:Windows上的WinSTL和Unix上的UnixSTL,因此它是便携式解决方案。所有特定于系统的元素都使用特征和策略指定,因此它是可扩展的框架。当然还提供了文件系统库。
答案 19 :(得分:0)
Boost Filesystem的initial_path()
行为与POSIX的getcwd()
相似,既不是你自己想要的,也不是argv[0]
加上其中任何一个就应该这样做。
你可能会注意到结果并不总是很好 - 你可能会得到像/foo/bar/../../baz/a.out
或/foo/bar//baz/a.out
这样的东西,但我相信它总会产生一个命名可执行文件的有效路径(请注意路径中的连续斜线折叠为一个。)
我之前使用envp
编写了一个解决方案(main()
的第三个参数在Linux上工作但在Windows上似乎不可行,所以我基本上推荐与其他人一样的解决方案以前,但附加解释为什么它实际上是正确的,即使结果不是很好。
答案 20 :(得分:0)
在POSIX平台上,您可以使用getcwd()。
在Windows上,您可以使用_getcwd(),因为已弃用getcwd()。
对于标准库,如果Boost足够标准,我会建议使用Boost :: filesystem,但它们似乎已从提案中删除了路径规范化。您可能需要等到TR2 becomes readily available才能获得完全标准的解决方案。
答案 21 :(得分:0)
图书馆解决方案(虽然我知道没有要求)。
如果你碰巧使用Qt:
QCoreApplication::applicationDirPath()
答案 22 :(得分:0)
像这样在realpath()
中使用stdlib.h
:
char *working_dir_path = realpath(".", NULL);
答案 23 :(得分:0)
从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
}