我有一个程序,它使用相对路径打开文件(例如'..')。
现在的问题是,当我从另一个目录执行程序时,相对路径不是相对于程序而是相对于工作目录。因此,如果我使用'/ path / to / program / myprog'启动程序,则无法找到该文件。
有没有办法独立于工作目录执行程序? Id est,as如果工作目录是程序所在的目录?或者我只是以一种过于复杂的方式思考,并且有一种更简单的方式来引用文件,该位置只能通过相对于程序文件路径的路径来识别?
答案 0 :(得分:4)
如果程序本身没有这样做,那就是一个糟糕的程序。糟糕的程序应该包含一些Bash脚本:
#!/bin/bash
set -e
cd $(readlink -f $(dirname $0))
exec ./myprog $*
上面的脚本确定了它所在的目录,然后将当前工作目录更改为该目录并从那里运行程序myprog
,透明地传递所有参数。因此,您必须将此脚本放在程序所在的同一目录中并运行它而不是程序。
假设您可以访问源代码并可以修复程序,那么使用proc fs确定程序的位置,然后使用绝对路径。
例如,/proc/self/exe
将始终是指向当前进程的二进制文件的符号链接。使用readlink
读取其值,然后删除可执行文件名,即可获得该目录。
答案 1 :(得分:2)
openat
打开一个相对于你传递的特定目录文件描述符的文件,但我认为这并不是你想要的(确切地说)。
您需要找到当前可执行文件所在的目录,然后创建相对于该目录的打开调用(使用字符串运算符构建路径openat
或将当前目录更改为该目录)
要查找可执行文件,您可以readlink
/proc/self/exe
。 readlink
读取符号链接指向的路径,/proc/self
是/proc/<PID>
的符号链接,其中<PID>
是当前进程的进程ID(在kernel),其下的exe
是指向该进程的可执行文件的符号链接。然后你需要删除该可执行文件的路径并使用它。
所有这一切,你通常应该避免编写程序,以期找到与其可执行文件相关的东西。
答案 2 :(得分:1)
前一段时间有一个问题如何查找the location of the executable in C 您可以使用此路径打开您的配置,资源等。
答案 3 :(得分:1)
一种方法是使用argv [0] - 程序的相对路径(例如./programs/test/a.out
)。如果您剪切程序名称并添加文件的相对路径,您将获得一个怪物(例如./programs/test/../../input_data
),但它应该可以工作。
答案 4 :(得分:1)
最简单的方法是将程序放在预先知道的位置(/ bin,/ usr / bin等)。如果没有,您可以使用argv [0],删除程序名称(最后一部分),并将其用作工作目录,以前缀所有相对路径(如果您希望相对路径相对于程序所在的位置)。
此外,您可以使用上述方法确定程序的路径(使用argv[0]
),然后使用此目录调用chdir()
。从那时起,所有相对路径都与程序所在的位置相关。但请注意,在这种情况下,您必须确定argv[0]
是否包含绝对路径。如果没有,您必须获取当前工作目录(getcwd()
),然后附加argv[0]
的目录部分。但请注意,更改当前工作目录。通常,好像用户给你一个文件路径作为参数,它不是一个好主意,它将相对于你当前的工作目录,而不是相对于程序存储的位置。
一些例子:想象一下你的程序存在于/usr/bin
中。您可以将您的计划称为:
/usr/bin/myprog
(那将是argv[0]
。修剪可执行文件的名称,你有你的目录。)或者,例如,在/usr
:
./bin/myprog
现在,argv[0]
是一个相对路径。您必须将当前工作目录(/usr
)添加到argv[0]
:/usr/./bin/myprog
中的目录,然后再次修剪可执行文件名称。该目录将再次为/usr/bin
。
答案 5 :(得分:0)
好吧,如果您的程序需要从某个位置打开文件,该位置取决于程序的安装位置,您应该将其作为编译时选项。让您的构建系统设置一些CPP宏,指示可以找到相关数据文件的目录。这就是在标准的“configure,make,make install”构建程序中配置的--datadir选项通常会做的事情。
当然,如果您真的想要,可以使用chdir
POSIX函数以编程方式更改工作目录。但就像我说的,如果一个程序需要知道它的位置,那么应该在编译时提供。然后,您不需要覆盖用户对工作目录的选择。
答案 6 :(得分:0)
不要使用相对路径。使用绝对路径。您可能在config.h头文件中定义了一个常量,指定可执行文件的安装位置。然后,将该字符串常量添加到您在代码中指定的任何相对路径。
答案 7 :(得分:0)
您可以从argv[0]
参数确定执行路径,但在执行此操作时要小心。
您所描述的是众所周知且预期的语义。用户会期望这种行为。
答案 8 :(得分:0)
以下是一些可用于在程序中查找安装路径的代码(将“test0002”替换为程序名称):
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <unistd.h>
///=============================================================================
std::string FindInstallPath()
{
std::string sret="";
int pid = (int)getpid();
bool b=false;
std::string sf, s;
std::stringstream ss;
ss << "/proc/" << pid << "/maps";
sf = ss.str();
std::ifstream ifs(sf.c_str());
size_t pos1, pos2;
while (!b && ifs.good())
{
std::getline(ifs, s);
if ((pos1 = s.rfind("test0002")) != std::string::npos)
{
if ((pos2 = s.find_first_of('/')) != std::string::npos)
sret = s.substr(pos2, pos1 - pos2);
b = true;
}
}
if (!b) sret = "";
ifs.close();
return sret;
}