简体   繁体   中英

get directory from file path c++

What is the simplest way to get the directory that a file is in? I'm using this to find the working directory.

string filename = "C:\MyDirectory\MyFile.bat" 

In this example, I should get "C:\MyDirectory".

The initialisation is incorrect as you need to escape the backslashes:

string filename = "C:\\MyDirectory\\MyFile.bat";

To extract the directory if present:

string directory;
const size_t last_slash_idx = filename.rfind('\\');
if (std::string::npos != last_slash_idx)
{
    directory = filename.substr(0, last_slash_idx);
}

The quick and dirty:

Note that you must also look for / because it is allowed alternative path separator on Windows

#include <string>
#include <iostream>

std::string dirnameOf(const std::string& fname)
{
     size_t pos = fname.find_last_of("\\/");
     return (std::string::npos == pos)
         ? ""
         : fname.substr(0, pos);
}

int main(int argc, const char *argv[])
{
     const std::string fname = "C:\\MyDirectory\\MyFile.bat";

     std::cout << dirnameOf(fname) << std::endl;
}

Use the Boost.filesystem parent_path() function.

Ex. argument c:/foo/bar => c:/foo

More examples here : path decomposition table and tutorial here .

The MFC way;

#include <afx.h>

CString GetContainingFolder(CString &file)
{
    CFileFind fileFind;
    fileFind.FindFile(file);
    fileFind.FindNextFile();
    return fileFind.GetRoot();
}

or, even simpler

CString path(L"C:\\my\\path\\document.txt");
path.Truncate(path.ReverseFind('\\'));

C++17 provides std::filesystem::path . It may be available in C++11 in ; link with -lstdc++fs. Note the function does not validate the path exists; use std::filesystem::status to determine type of file (which may be filetype::notfound)

As Question is old but I would like to add an answer so that it will helpful for others.
in Visual c++ you can use CString or char array also

CString filename = _T("C:\\MyDirectory\\MyFile.bat");  
PathRemoveFileSpec(filename); 

OUTPUT:

C:\\MyDirectory

Include Shlwapi.h in your header files.

MSDN LINK here you can check example.

You can use the _spliltpath function available in stdlib.h header. Please refer to this link for the same.

http://msdn.microsoft.com/en-us/library/aa273364%28v=VS.60%29.aspx

A very simple cross-platform solution (as adapted from this example for string::find_last_of ):

std::string GetDirectory (const std::string& path)
{
    size_t found = path.find_last_of("/\\");
    return(path.substr(0, found));
}

This works for both cases where the slashes can be either backward or forward pointing (or mixed), since it merely looks for the last occurrence of either in the string path .

However, my personal preference is using the Boost::Filesystem libraries to handle operations like this. An example:

std::string GetDirectory (const std::string& path)
{
    boost::filesystem::path p(path);
    return(p.parent_path().string());
}

Although, if getting the directory path from a string is the only functionality you need, then Boost might be a bit overkill (especially since Boost::Filesystem is one of the few Boost libraries that aren't header-only). However, AFIK, Boost::Filesystem had been approved to be included into the TR2 standard, but might not be fully available until the C++14 or C++17 standard (likely the latter, based on this answer ), so depending on your compiler (and when you're reading this), you may not even need to compile these separately anymore since they might be included with your system already. For example, Visual Studio 2012 can already use some of the TR2 filesystem components (according to this post ), though I haven't tried it since I'm still using Visual Studio 2010...

This is proper winapi solution:

CString csFolder = _T("c:\temp\file.ext");
PathRemoveFileSpec(csFolder.GetBuffer(0));
csFolder.ReleaseBuffer(-1);

Since C++17 you can use std::filesystem::parent_path :

#include <filesystem>
#include <iostream>

int main() {
    std::string filename = "C:\\MyDirectory\\MyFile.bat";
    std::string directory = std::filesystem::path(filename).parent_path().u8string();
    std::cout << directory << std::endl;
}

If you have access to Qt, you can also do it like this:

std::string getDirectory(const std::string & file_path)
{
   return QFileInfo(QString(file_path)).absolutePath().toStdString();
}

The way of Beetle)

#include<tchar.h>

int GetDir(TCHAR *fullPath, TCHAR *dir) {
    const int buffSize = 1024;

    TCHAR buff[buffSize] = {0};
    int buffCounter = 0;
    int dirSymbolCounter = 0;

    for (int i = 0; i < _tcslen(fullPath); i++) {
        if (fullPath[i] != L'\\') {
            if (buffCounter < buffSize) buff[buffCounter++] = fullPath[i];
            else return -1;
        } else {
            for (int i2 = 0; i2 < buffCounter; i2++) {
                dir[dirSymbolCounter++] = buff[i2];
                buff[i2] = 0;
            }

            dir[dirSymbolCounter++] = fullPath[i];
            buffCounter = 0;
        }
    }

    return dirSymbolCounter;
}

Using :

TCHAR *path = L"C:\\Windows\\System32\\cmd.exe";
TCHAR  dir[1024] = {0};

GetDir(path, dir);
wprintf(L"%s\n%s\n", path, dir);

You can simply search the last "\\" and then cut the string:

string filePath = "C:\MyDirectory\MyFile.bat" 
size_t slash = filePath.find_last_of("\");
string dirPath = (slash != std::string::npos) ? filePath.substr(0, slash) : filePath;

make sure in Linux to search "/" instead of "\\":

size_t slash = filePath.find_last_of("/");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM