c++oding="utf-8" ?>
std::filesystem::current_path() 返回进程启动时 shell 所在路径,而非可执行文件目录;它返回绝对路径,可用 std::filesystem::absolute() 将相对路径转为基于当前工作目录的绝对路径。

用 std::filesystem::current_path() 获取当前工作目录
程序启动时的当前工作目录(CWD)不等于可执行文件所在路径,而是进程被启动时 shell 所在的路径。想拿到它,最直接的方式是调用 std::filesystem::current_path()(C++17 起支持)。它返回一个 std::filesystem::path 对象,本身就是绝对路径(除非系统异常,否则不会返回相对路径)。
常见错误是误以为它返回的是 exe 所在目录——不是。比如你在 /home/user 下执行 ./build/myapp,current_path() 返回的就是 /home/user,不是 /home/user/build。
实操建议:
- 确保编译器支持 C++17 或更高(如 g++ -std=c++17)
- 链接时无需额外库(libstdc++/libc++ 内置支持)
- 若需兼容 Windows,注意路径分隔符会自动适配(
path.string()返回"C:\foo\bar"或"/foo/bar")
把相对路径转成绝对路径:用 std::filesystem::absolute()
如果你手里有个相对路径(比如配置文件名 "config.json" 或子目录 "data/"),想基于当前工作目录展开成完整路径,就该用 std::filesystem::absolute()。
它内部会自动拼接 current_path() 和输入路径,并规范化(比如处理 "./sub/../file.txt" → "file.txt")。
示例:
auto cwd = std::filesystem::current_path();
auto abs_path = std::filesystem::absolute("config.json"); // 等价于 cwd / "config.json"
// abs_path.string() 可能是 "/home/user/config.json"
注意点:
- 输入为空字符串或只含空格时,
absolute()行为未定义,务必先校验 - 如果输入已经是绝对路径(如
"/etc/passwd"或"C:\temp"),absolute()直接返回原路径,不做拼接 - 不会检查路径是否存在,只做字符串拼接和规范化
Windows 下获取 exe 所在目录?别依赖 current_path()
很多人真正想要的其实是“程序自己放在哪”,而不是“我在哪启动的它”。这和 current_path() 完全无关,得走平台 API。
Windows 上可用 GetModuleFileNameA(NULL, ...) 拿到完整 exe 路径,再用 std::filesystem::path::parent_path() 截掉文件名:
#ifdef _WIN32
#include <windows.h>
#include <filesystem>
std::string get_exe_dir() {
char buf[MAX_PATH];
GetModuleFileNameA(NULL, buf, MAX_PATH);
return std::filesystem::path(buf).parent_path().string();
}
#endif
</filesystem></windows.h>
Linux/macOS 则要读取 /proc/self/exe 符号链接(macOS 用 _NSGetExecutablePath())。这些都不是标准 C++,必须条件编译。
关键提醒:
- 不要试图用
current_path()+ argv[0] 拼凑——argv[0] 可能是相对路径、别名、甚至空字符串 - 即使拿到 exe 路径,也要注意:打包工具(如 PyInstaller 风格的 C++ 打包器)可能解压到临时目录,路径每次运行都不同
路径操作容易踩的坑:编码、权限、符号链接
std::filesystem 默认按系统 locale 解码路径字节,遇到非 UTF-8 文件名(比如某些 GBK 系统上的中文路径),path.string() 可能乱码或抛异常。Linux 下尤其明显。
权限问题常被忽略:调用 current_path() 本身不检查权限,但后续 exists() 或 is_directory() 可能因无读权限返回 false,不是路径错了,是没权限访问。
符号链接更隐蔽:absolute() 不自动解析 symlink,"/a/b" → symlink to /x/y,那么 absolute("/a/b/file.txt") 还是返回 "/a/b/file.txt",不是 "/x/y/file.txt"。真要解析,得用 std::filesystem::canonical(),但它要求路径存在且可访问。
所以实际项目中:
- 对用户传入的路径,优先用
canonical()(如果确定它应存在) - 记录日志时,用
path.generic_string()更安全(返回 / 分隔的 UTF-8 字符串) - 跨平台路径拼接一律用
/运算符:path / "sub" / "file.txt",别手拼字符串
路径的“绝对”与否,取决于你问的是谁的上下文:启动位置、可执行位置、还是某个配置项的基准位置。混淆这三者,是绝大多数路径 bug 的根源。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











