Extracting the immediate parent directory from a file path using boost

3.8k views Asked by At

Assuming I have

String t = "c:/foo/foo1/foo2/foo3/file.txt"

I want to extract "foo3/file.txt".

How can I do this (using boost or std)?

Here is what I've been trying to so far:

boost::filesystem::path pathToObject(t);

Using pathToObject.filename() I can extract the file name of course. And I've played around with t.find_last_of("/") but I really need like t.find_second_to_last_of("/").

5

There are 5 answers

2
lakeweb On

It is rather odd to extract a path like that. Maybe you are looking for a relative path? boost filesystem has a tool for that. Be sure to give the documentation a good look over. But to answer your question:

namespace bfs= boost::filesystem;
    int main( ) {
        bfs::path path( "c:/foo/foo1/foo2/foo3/file.txt" );
        bfs::path target( path );
        target.remove_filename( );
        target= target.filename( ) / path.filename( );
        std::cout << target << std::endl;
    }
3
Russell Newquist On

I don't have a compiler handy to test it, but based on the example here, this code should basically work or point you in about the right direction. It could probably be simplified a little bit even from what I've written here.

path p1( "c:/foo/foo1/foo2/foo3/file.txt" );
path p2;
for (path::iterator it(p1.end()), int i = 0; it != p1.begin() && i < 2; --it, ++i) {
  path temp = p2;
  p2 = it;
  p2 /= temp;
}
5
Hermann Döppes On

string::find_last_of has an optional argument which lets you specify how far into the string you are looking.

So you can define

size_t second_to_last = t.find_last_of("/", t.find_last_of("/")-1);
std::string file_with_parent = t.substr(second_to_last+1);

The second argument tells him to only search before the last /.

WARNING: This might differ from what you want if you have stuff like "C:/bli/bla//blubb.txt". In general, paths can be complex and confusing and trying to conquer them with string manipulation will only work for very well-behaved input, which one usually can't assume.

I therefore recommended using a proper tool for this job.* But since the question claimed that find_last_of wouldn't do the job I felt quite compelled to remind people that the standard facilities are not entirely as impotent as many seem to believe them to be.

*I suspect the boost path lib to be one but I have never worked with it.

1
Brad Wardell On

Here is the solution I ended up using:

std::string t = pathObject.parent_path().filename().string();
t.append("/");
t.append(pathObject.filename().string());

Using parent_path gave me just the path. Then I used the filename to extract just the directory. Then I appended the filename of the child directory.

0
Pabitra Dash On

Following method return immediate parent directory.

#include <string>
string getParentDirectory(string& filePath)
{
    if (filePath.empty() == false)
    {
        size_t toPos = filePath.find_last_of('\\') - 1;
        if (toPos != string::npos)
        {
            size_t fromPos = filePath.find_last_of('\\', toPos);
            if (fromPos != string::npos)
            {
                return filePath.substr(fromPos + 1, toPos - fromPos);
            }
        }
    }

    return "";
}

int main() 
{
    string str = "D:\\Devs\\Test\\sprite.png";

    string parentDir = getParentDirectory(str);
    return 0;
}

It prints the value of parentDir is "Test".