Violet Giraffe
Violet Giraffe

Reputation: 33579

Converting a relative path to absolute on Mac and Linux

This is what I'm trying to implement:

CString r = CDir("/users/administrator/path/3/4/5").absolutePathFor("../../2/../3/");

r should now contain "/users/administrator/path/3/3/".

On Windows this is done with GetFullPathName. On Linux and Mac there's plain old C function realpath() that almost does the trick. However, it has one huge issue: it seems to only work with paths that actually exist. In my example some part of the path doesn't exist, and that part is truncated from the result returned by realpath. What other functions are available on Mac and Linux that can solve my task?

Upvotes: 1

Views: 1619

Answers (1)

meneldal
meneldal

Reputation: 1737

You mean you want to compute what the path would be even if the path doesn't exist (so you can't ask the OS about it)?

In this case I guess you can make a function that would take the current directory parameter and the relative path as arguments. You then check what you have between every /. If it's "." you ignore it, if it's ".." you remove the last directory from the current path, if it's something else you add it to the current path.

A good way to implement it would be to use a stack for the path (you push/pop) and a queue for the relative path. Converting the string to this should be pretty easy. Like for example (for making the base path)

I assume BasePath is the input string parameter for the path

std::stack<string>path;
string temp;
for (int i=0;i<BasePath.size()
    if(BasePath[i]!='/')
        temp+=BasePath[i];
    else
        path.push(temp), temp.clear();

This is pretty ugly and could be done with regular expressions but since you said you don't have Boost I'll also assume you don't have C++11 and for this complexity you can get away without it anyway.

For the interesting part you can do it like that

while(!relativepath.empty())
{
    if(relativepath.front()==".."
        path.pop();
    if(relativepath.front()=="." {}
    else
        path.push(relativepath.front());
   relativepath.pop();
}

I'm not sure it's what you wanted but it's not so hard to make and you can easily adapt for Windows/Linux by changing the separator.

Upvotes: 1

Related Questions