如何在Linux中使用它的相对路径打开文件?

时间:2010-10-21 13:36:22

标签: c++ c linux path

我有一个程序,它使用相对路径打开文件(例如'..')。

现在的问题是,当我从另一个目录执行程序时,相对路径不是相对于程序而是相对于工作目录。因此,如果我使用'/ path / to / program / myprog'启动程序,则无法找到该文件。

有没有办法独立于工作目录执行程序? Id est,as如果工作目录是程序所在的目录?或者我只是以一种过于复杂的方式思考,并且有一种更简单的方式来引用文件,该位置只能通过相对于程序文件路径的路径来识别?

9 个答案:

答案 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/exereadlink读取符号链接指向的路径,/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;
}