Get a file name from a path












65















What is the simplest way to get the file name that from a path?



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


In this example, I should get "MyFile". without extension.










share|improve this question




















  • 1





    Search from the back until you hit a backspace?

    – Kerrek SB
    Dec 15 '11 at 13:13






  • 2





    @KerrekSB, you mean backslash ;)

    – Nim
    Dec 15 '11 at 13:14











  • i have an std::string that contains a path of a file "c:\MyDirectory\Myfile.pdf" i need to rename this file to myfile_md.pdf so i need to get the file name from the path.

    – nidhal
    Dec 15 '11 at 13:20






  • 1





    If you need to do a lot of work with file paths consider using Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm

    – edA-qa mort-ora-y
    Dec 15 '11 at 13:26






  • 2





    @Nim: Yes! I must have been spacing out...

    – Kerrek SB
    Dec 15 '11 at 13:42
















65















What is the simplest way to get the file name that from a path?



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


In this example, I should get "MyFile". without extension.










share|improve this question




















  • 1





    Search from the back until you hit a backspace?

    – Kerrek SB
    Dec 15 '11 at 13:13






  • 2





    @KerrekSB, you mean backslash ;)

    – Nim
    Dec 15 '11 at 13:14











  • i have an std::string that contains a path of a file "c:\MyDirectory\Myfile.pdf" i need to rename this file to myfile_md.pdf so i need to get the file name from the path.

    – nidhal
    Dec 15 '11 at 13:20






  • 1





    If you need to do a lot of work with file paths consider using Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm

    – edA-qa mort-ora-y
    Dec 15 '11 at 13:26






  • 2





    @Nim: Yes! I must have been spacing out...

    – Kerrek SB
    Dec 15 '11 at 13:42














65












65








65


13






What is the simplest way to get the file name that from a path?



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


In this example, I should get "MyFile". without extension.










share|improve this question
















What is the simplest way to get the file name that from a path?



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


In this example, I should get "MyFile". without extension.







c++ visual-c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 18 '13 at 0:20









Prashant Kumar

11.2k134059




11.2k134059










asked Dec 15 '11 at 13:05









nidhalnidhal

4743814




4743814








  • 1





    Search from the back until you hit a backspace?

    – Kerrek SB
    Dec 15 '11 at 13:13






  • 2





    @KerrekSB, you mean backslash ;)

    – Nim
    Dec 15 '11 at 13:14











  • i have an std::string that contains a path of a file "c:\MyDirectory\Myfile.pdf" i need to rename this file to myfile_md.pdf so i need to get the file name from the path.

    – nidhal
    Dec 15 '11 at 13:20






  • 1





    If you need to do a lot of work with file paths consider using Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm

    – edA-qa mort-ora-y
    Dec 15 '11 at 13:26






  • 2





    @Nim: Yes! I must have been spacing out...

    – Kerrek SB
    Dec 15 '11 at 13:42














  • 1





    Search from the back until you hit a backspace?

    – Kerrek SB
    Dec 15 '11 at 13:13






  • 2





    @KerrekSB, you mean backslash ;)

    – Nim
    Dec 15 '11 at 13:14











  • i have an std::string that contains a path of a file "c:\MyDirectory\Myfile.pdf" i need to rename this file to myfile_md.pdf so i need to get the file name from the path.

    – nidhal
    Dec 15 '11 at 13:20






  • 1





    If you need to do a lot of work with file paths consider using Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm

    – edA-qa mort-ora-y
    Dec 15 '11 at 13:26






  • 2





    @Nim: Yes! I must have been spacing out...

    – Kerrek SB
    Dec 15 '11 at 13:42








1




1





Search from the back until you hit a backspace?

– Kerrek SB
Dec 15 '11 at 13:13





Search from the back until you hit a backspace?

– Kerrek SB
Dec 15 '11 at 13:13




2




2





@KerrekSB, you mean backslash ;)

– Nim
Dec 15 '11 at 13:14





@KerrekSB, you mean backslash ;)

– Nim
Dec 15 '11 at 13:14













i have an std::string that contains a path of a file "c:\MyDirectory\Myfile.pdf" i need to rename this file to myfile_md.pdf so i need to get the file name from the path.

– nidhal
Dec 15 '11 at 13:20





i have an std::string that contains a path of a file "c:\MyDirectory\Myfile.pdf" i need to rename this file to myfile_md.pdf so i need to get the file name from the path.

– nidhal
Dec 15 '11 at 13:20




1




1





If you need to do a lot of work with file paths consider using Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm

– edA-qa mort-ora-y
Dec 15 '11 at 13:26





If you need to do a lot of work with file paths consider using Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm

– edA-qa mort-ora-y
Dec 15 '11 at 13:26




2




2





@Nim: Yes! I must have been spacing out...

– Kerrek SB
Dec 15 '11 at 13:42





@Nim: Yes! I must have been spacing out...

– Kerrek SB
Dec 15 '11 at 13:42












18 Answers
18






active

oldest

votes


















25














_splitpath should do what you need. You could of course do it manually but _splitpath handles all special cases as well.



EDIT:



As BillHoag mentioned it is recommended to use the more safe version of _splitpath called _splitpath_s when available.



Or if you want something portable you could just do something like this



std::vector<std::string> splitpath(
const std::string& str
, const std::set<char> delimiters)
{
std::vector<std::string> result;

char const* pch = str.c_str();
char const* start = pch;
for(; *pch; ++pch)
{
if (delimiters.find(*pch) != delimiters.end())
{
if (start != pch)
{
std::string str(start, pch);
result.push_back(str);
}
else
{
result.push_back("");
}
start = pch + 1;
}
}
result.push_back(start);

return result;
}

...
std::set<char> delims{'\'};

std::vector<std::string> path = splitpath("C:\MyDirectory\MyFile.bat", delims);
cout << path.back() << endl;





share|improve this answer





















  • 2





    There's no _splitpath in any of the includes on my machine.

    – James Kanze
    Dec 15 '11 at 13:22






  • 6





    I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

    – James Kanze
    Dec 15 '11 at 13:49






  • 1





    @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

    – Synetech
    Apr 4 '12 at 3:35






  • 1





    @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

    – James Kanze
    Apr 4 '12 at 7:19






  • 3





    @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

    – Synetech
    Apr 4 '12 at 19:05



















39














A possible solution:



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

// Remove directory if present.
// Do this before extension removal incase directory has a period character.
const size_t last_slash_idx = filename.find_last_of("\/");
if (std::string::npos != last_slash_idx)
{
filename.erase(0, last_slash_idx + 1);
}

// Remove extension if present.
const size_t period_idx = filename.rfind('.');
if (std::string::npos != period_idx)
{
filename.erase(period_idx);
}





share|improve this answer


























  • the simplest is always the best!

    – Jean-François Fabre
    Apr 4 '18 at 15:12



















37














The simplest solution is to use something like boost::filesystem. If
for some reason this isn't an option...



Doing this correctly will require some system dependent code: under
Windows, either '\' or '/' can be a path separator; under Unix,
only '/' works, and under other systems, who knows. The obvious
solution would be something like:



std::string
basename( std::string const& pathname )
{
return std::string(
std::find_if( pathname.rbegin(), pathname.rend(),
MatchPathSeparator() ).base(),
pathname.end() );
}


, with MatchPathSeparator being defined in a system dependent header
as either:



struct MatchPathSeparator
{
bool operator()( char ch ) const
{
return ch == '/';
}
};


for Unix, or:



struct MatchPathSeparator
{
bool operator()( char ch ) const
{
return ch == '\' || ch == '/';
}
};


for Windows (or something still different for some other unknown
system).



EDIT: I missed the fact that he also wanted to suppress the extention.
For that, more of the same:



std::string
removeExtension( std::string const& filename )
{
std::string::const_reverse_iterator
pivot
= std::find( filename.rbegin(), filename.rend(), '.' );
return pivot == filename.rend()
? filename
: std::string( filename.begin(), pivot.base() - 1 );
}


The code is a little bit more complex, because in this case, the base of
the reverse iterator is on the wrong side of where we want to cut.
(Remember that the base of a reverse iterator is one behind the
character the iterator points to.) And even this is a little dubious: I
don't like the fact that it can return an empty string, for example.
(If the only '.' is the first character of the filename, I'd argue
that you should return the full filename. This would require a little
bit of extra code to catch the special case.)
}






share|improve this answer





















  • 8





    How about using string::find_last_of instead of manipulating reverse iterators?

    – Luc Touraille
    Dec 15 '11 at 14:04











  • @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

    – James Kanze
    Dec 15 '11 at 15:35











  • Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

    – IInspectable
    May 2 '17 at 10:39



















33














The task is fairly simple as the base filename is just the part of the string starting at the last delimeter for folders:



std::string base_filename = path.substr(path.find_last_of("/\") + 1)


If the extension is to be removed as well the only thing to do is find the last . and take a substr to this point



std::string::size_type const p(base_filename.find_last_of('.'));
std::string file_without_extension = base_filename.substr(0, p);


Perhaps there should be a check to cope with files solely consisting of extensions (ie .bashrc...)



If you split this up into seperate functions you're flexible to reuse the single tasks:



template<class T>
T base_name(T const & path, T const & delims = "/\")
{
return path.substr(path.find_last_of(delims) + 1);
}
template<class T>
T remove_extension(T const & filename)
{
typename T::size_type const p(filename.find_last_of('.'));
return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
}


The code is templated to be able to use it with different std::basic_string instances (i.e. std::string & std::wstring...)



The downside of the templation is the requirement to specify the template parameter if a const char * is passed to the functions.



So you could either:



A) Use only std::string instead of templating the code



std::string base_name(std::string const & path)
{
return path.substr(path.find_last_of("/\") + 1);
}


B) Provide wrapping function using std::string (as intermediates which will likely be inlined / optimized away)



inline std::string string_base_name(std::string const & path)
{
return base_name(path);
}


C) Specify the template parameter when calling with const char *.



std::string base = base_name<std::string>("some/path/file.ext");


Result



std::string filepath = "C:\MyDirectory\MyFile.bat";
std::cout << remove_extension(base_name(filepath)) << std::endl;


Prints



MyFile





share|improve this answer
























  • In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

    – avtomaton
    Aug 27 '15 at 8:03











  • @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

    – Pixelchemist
    Aug 27 '15 at 9:14











  • I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

    – avtomaton
    Aug 27 '15 at 10:14











  • Very nice explanation. It enhances the structural understanding of the problem. Thanks

    – hell_ical_vortex
    May 18 '16 at 7:15



















12














You can also use the shell Path APIs PathFindFileName, PathRemoveExtension. Probably worse than _splitpath for this particular problem, but those APIs are very useful for all kinds of path parsing jobs and they take UNC paths, forward slashes and other weird stuff into account.



wstring filename = L"C:\MyDirectory\MyFile.bat";
wchar_t* filepart = PathFindFileName(filename.c_str());
PathRemoveExtension(filepart);


http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx



The drawback is that you have to link to shlwapi.lib, but I'm not really sure why that's a drawback.






share|improve this answer
























  • My preferred solution for getting a filename from a path.

    – mrt
    May 12 '17 at 6:32



















11














If you can use boost,



#include <boost/filesystem.hpp>
path p("C:\MyDirectory\MyFile.bat");
string basename = p.filename().string();
//or
//string basename = path("C:\MyDirectory\MyFile.bat").filename().string();


This is all.



I recommend you to use boost library. Boost gives you a lot of conveniences when you work with C++. It supports almost all platforms.
If you use Ubuntu, you can install boost library by only one line sudo apt-get install libboost-all-dev (ref. How to Install boost on Ubuntu?)






share|improve this answer

































    10














    Function:



    #include <string>

    std::string
    basename(const std::string &filename)
    {
    if (filename.empty()) {
    return {};
    }

    auto len = filename.length();
    auto index = filename.find_last_of("/\");

    if (index == std::string::npos) {
    return filename;
    }

    if (index + 1 >= len) {

    len--;
    index = filename.substr(0, len).find_last_of("/\");

    if (len == 0) {
    return filename;
    }

    if (index == 0) {
    return filename.substr(1, len - 1);
    }

    if (index == std::string::npos) {
    return filename.substr(0, len);
    }

    return filename.substr(index + 1, len - index - 1);
    }

    return filename.substr(index + 1, len - index);
    }


    Tests:



    #define CATCH_CONFIG_MAIN
    #include <catch/catch.hpp>

    TEST_CASE("basename")
    {
    CHECK(basename("") == "");
    CHECK(basename("no_path") == "no_path");
    CHECK(basename("with.ext") == "with.ext");
    CHECK(basename("/no_filename/") == "no_filename");
    CHECK(basename("no_filename/") == "no_filename");
    CHECK(basename("/no/filename/") == "filename");
    CHECK(basename("/absolute/file.ext") == "file.ext");
    CHECK(basename("../relative/file.ext") == "file.ext");
    CHECK(basename("/") == "/");
    CHECK(basename("c:\windows\path.ext") == "path.ext");
    CHECK(basename("c:\windows\no_filename\") == "no_filename");
    }





    share|improve this answer

































      7














      From C++ Docs - string::find_last_of



      #include <iostream>       // std::cout
      #include <string> // std::string

      void SplitFilename (const std::string& str) {
      std::cout << "Splitting: " << str << 'n';
      unsigned found = str.find_last_of("/\");
      std::cout << " path: " << str.substr(0,found) << 'n';
      std::cout << " file: " << str.substr(found+1) << 'n';
      }

      int main () {
      std::string str1 ("/usr/bin/man");
      std::string str2 ("c:\windows\winhelp.exe");

      SplitFilename (str1);
      SplitFilename (str2);

      return 0;
      }


      Outputs:



      Splitting: /usr/bin/man
      path: /usr/bin
      file: man
      Splitting: c:windowswinhelp.exe
      path: c:windows
      file: winhelp.exe





      share|improve this answer
























      • Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

        – congusbongus
        Mar 14 '16 at 23:53











      • @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

        – jave.web
        Mar 15 '16 at 11:05













      • @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

        – winux
        Sep 22 '16 at 8:09













      • @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

        – jave.web
        Sep 23 '16 at 13:07











      • @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

        – jave.web
        Sep 23 '16 at 13:07





















      6














      The Simplest way in cpp17 is:



      use the #include experimental/filesystem and filename() for filename with extension and stem() without extension.



         #include <iostream>
      #include <experimental/filesystem>
      namespace fs = std::experimental::filesystem;

      int main()
      {
      string filename = "C:\MyDirectory\MyFile.bat";

      std::cout << fs::path(filename).filename() << 'n'
      << fs::path(filename).stem() << 'n'
      << fs::path("/foo/bar.txt").filename() << 'n'
      << fs::path("/foo/bar.txt").stem() << 'n'
      << fs::path("/foo/.bar").filename() << 'n'
      << fs::path("/foo/bar/").filename() << 'n'
      << fs::path("/foo/.").filename() << 'n'
      << fs::path("/foo/..").filename() << 'n'
      << fs::path(".").filename() << 'n'
      << fs::path("..").filename() << 'n'
      << fs::path("/").filename() << 'n';
      }


      output:



      MyFile.bat
      MyFile
      "bar.txt"
      ".bar"
      "."
      "."
      ".."
      "."
      ".."
      "/"


      Ref: cppreference






      share|improve this answer

































        5














        C++11 variant (inspired by James Kanze's version) with uniform initialization and anonymous inline lambda.



        std::string basename(const std::string& pathname)
        {
        return {std::find_if(pathname.rbegin(), pathname.rend(),
        (char c) { return c == '/'; }).base(),
        pathname.end()};
        }


        It does not remove the file extension though.






        share|improve this answer


























        • Short and sweet, although it only works with non-Windows paths.

          – Volomike
          Mar 5 '16 at 18:33











        • you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

          – ziomq1991
          Apr 19 '16 at 9:57











        • To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

          – Gidfiddle
          Oct 27 '17 at 6:14



















        4














        this is the only thing that actually finally worked for me:



        #include "Shlwapi.h"

        CString some_string = "c:\path\hello.txt";
        LPCSTR file_path = some_string.GetString();
        LPCSTR filepart_c = PathFindFileName(file_path);
        LPSTR filepart = LPSTR(filepart_c);
        PathRemoveExtension(filepart);


        pretty much what Skrymsli suggested but doesn't work with wchar_t*,
        VS Enterprise 2015



        _splitpath worked as well, but I don't like having to guess at how many char[?] characters I'm going to need; some people probably need this control, i guess.



        CString c_model_name = "c:\path\hello.txt";
        char drive[200];
        char dir[200];
        char name[200];
        char ext[200];
        _splitpath(c_model_name, drive, dir, name, ext);


        I don't believe any includes were needed for _splitpath. No external libraries (like boost) were needed for either of these solutions.






        share|improve this answer































          3














          I would do it by...



          Search backwards from the end of the string until you find the first backslash/forward slash.



          Then search backwards again from the end of the string until you find the first dot (.)



          You then have the start and end of the file name.



          Simples...






          share|improve this answer


























          • Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

            – James Kanze
            Dec 15 '11 at 13:32











          • Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

            – TomP89
            Dec 15 '11 at 13:48











          • You still have to find the last dot, not the first. (Reverse iterators are your friend!)

            – James Kanze
            Dec 15 '11 at 13:56











          • Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

            – TomP89
            Dec 15 '11 at 13:57











          • Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

            – James Kanze
            Dec 15 '11 at 14:02



















          3














          The boost filesystem library is also available as the experimental/filesystem library and was merged into ISO C++ for C++17. You can use it like this:



          #include <iostream>
          #include <experimental/filesystem>

          namespace fs = std::experimental::filesystem;

          int main () {
          std::cout << fs::path("/foo/bar.txt").filename() << 'n'
          }


          Output:



          "bar.txt"


          It also works for std::string objects.






          share|improve this answer


























          • Note that the later answer of @eliastem is the same...

            – Adam Erickson
            Jul 4 '18 at 1:25



















          2














          m_szFilePath.MakeLower();
          CFileFind finder;
          DWORD buffSize = MAX_PATH;
          char longPath[MAX_PATH];
          DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

          if( result == 0)
          {
          m_bExists = FALSE;
          return;
          }
          m_szFilePath = CString(longPath);
          m_szFilePath.Replace("/","\");
          m_szFilePath.Trim();
          //check if it does not ends in => remove it
          int length = m_szFilePath.GetLength();
          if( length > 0 && m_szFilePath[length - 1] == '\' )
          {
          m_szFilePath.Truncate( length - 1 );
          }
          BOOL bWorking = finder.FindFile(this->m_szFilePath);
          if(bWorking){
          bWorking = finder.FindNextFile();
          finder.GetCreationTime(this->m_CreationTime);
          m_szFilePath = finder.GetFilePath();
          m_szFileName = finder.GetFileName();

          this->m_szFileExtension = this->GetExtension( m_szFileName );

          m_szFileTitle = finder.GetFileTitle();
          m_szFileURL = finder.GetFileURL();
          finder.GetLastAccessTime(this->m_LastAccesTime);
          finder.GetLastWriteTime(this->m_LastWriteTime);
          m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
          m_szRootDirectory = finder.GetRoot();
          m_bIsArchive = finder.IsArchived();
          m_bIsCompressed = finder.IsCompressed();
          m_bIsDirectory = finder.IsDirectory();
          m_bIsHidden = finder.IsHidden();
          m_bIsNormal = finder.IsNormal();
          m_bIsReadOnly = finder.IsReadOnly();
          m_bIsSystem = finder.IsSystem();
          m_bIsTemporary = finder.IsTemporary();
          m_bExists = TRUE;
          finder.Close();
          }else{
          m_bExists = FALSE;
          }


          The variable m_szFileName contains the fileName.






          share|improve this answer



















          • 3





            wow - that's a lot of code for "get file name" from path... :)

            – Nim
            Dec 15 '11 at 13:15






          • 4





            @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

            – James Kanze
            Dec 15 '11 at 13:36











          • I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

            – Lucian
            Dec 15 '11 at 13:42



















          2














          Dont use _splitpath() and _wsplitpath(). They are not safe, and they are obsolete!



          Instead, use their safe versions, namely _splitpath_s() and _wsplitpath_s()






          share|improve this answer































            2














            This should work too :



            // strPath = "C:\Dir\File.bat" for example
            std::string getFileName(const std::string& strPath)
            {
            size_t iLastSeparator = 0;
            return strPath.substr((iLastSeparator = strPath.find_last_of("\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
            }


            If you can use it, Qt provide QString (with split, trim etc), QFile, QPath, QFileInfo etc to manipulate files, filenames and directories. And of course it's also cross plaftorm.






            share|improve this answer





















            • 4





              For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

              – Luc Touraille
              Dec 15 '11 at 14:07











            • edited. But the point was to make it short, as several working answers already have been given.

              – typedef
              Dec 15 '11 at 14:32






            • 1





              I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

              – taktak004
              Jan 22 '14 at 12:35











            • @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

              – phenmod
              Dec 8 '15 at 10:08





















            0














            For long time I was looking for a function able to properly decompose file path. For me this code is working perfectly for both Linux and Windows.



            void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
            {
            #if defined _WIN32
            const char *lastSeparator = strrchr(filePath, '\');
            #else
            const char *lastSeparator = strrchr(filePath, '/');
            #endif

            const char *lastDot = strrchr(filePath, '.');
            const char *endOfPath = filePath + strlen(filePath);
            const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
            const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

            if(fileDir)
            _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

            if(fileName)
            _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

            if(fileExt)
            _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
            }


            Example results are:




            fileDir: ''
            fileName: ''
            fileExt: ''

            [.htaccess]
            fileDir: ''
            fileName: '.htaccess'
            fileExt: ''

            [a.exe]
            fileDir: ''
            fileName: 'a'
            fileExt: '.exe'

            [ab.c]
            fileDir: 'a'
            fileName: 'b'
            fileExt: '.c'

            [git-archive]
            fileDir: ''
            fileName: 'git-archive'
            fileExt: ''

            [git-archive.exe]
            fileDir: ''
            fileName: 'git-archive'
            fileExt: '.exe'

            [D:Gitmingw64libexecgit-core.htaccess]
            fileDir: 'D:Gitmingw64libexecgit-core'
            fileName: '.htaccess'
            fileExt: ''

            [D:Gitmingw64libexecgit-corea.exe]
            fileDir: 'D:Gitmingw64libexecgit-core'
            fileName: 'a'
            fileExt: '.exe'

            [D:Gitmingw64libexecgit-coregit-archive.exe]
            fileDir: 'D:Gitmingw64libexecgit-core'
            fileName: 'git-archive'
            fileExt: '.exe'

            [D:Gitmingw64libexecgit.coregit-archive.exe]
            fileDir: 'D:Gitmingw64libexecgit.core'
            fileName: 'git-archive'
            fileExt: '.exe'

            [D:Gitmingw64libexecgit-coregit-archiveexe]
            fileDir: 'D:Gitmingw64libexecgit-core'
            fileName: 'git-archiveexe'
            fileExt: ''

            [D:Gitmingw64libexecgit.coregit-archiveexe]
            fileDir: 'D:Gitmingw64libexecgit.core'
            fileName: 'git-archiveexe'
            fileExt: ''


            I hope this helps you also :)






            share|improve this answer































              0














              shlwapi.lib/dll uses the HKCU registry hive internally.



              It's best not to link to shlwapi.lib if you're creating a library or the product does not have a UI. If you're writing a lib then your code can be used in any project including those that don't have UIs.



              If you're writing code that runs when a user is not logged in (e.g. service [or other] set to start at boot or startup) then there's no HKCU. Lastly, shlwapi are settlement functions; and as a result high on the list to deprecate in later versions of Windows.






              share|improve this answer

























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8520560%2fget-a-file-name-from-a-path%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                18 Answers
                18






                active

                oldest

                votes








                18 Answers
                18






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                25














                _splitpath should do what you need. You could of course do it manually but _splitpath handles all special cases as well.



                EDIT:



                As BillHoag mentioned it is recommended to use the more safe version of _splitpath called _splitpath_s when available.



                Or if you want something portable you could just do something like this



                std::vector<std::string> splitpath(
                const std::string& str
                , const std::set<char> delimiters)
                {
                std::vector<std::string> result;

                char const* pch = str.c_str();
                char const* start = pch;
                for(; *pch; ++pch)
                {
                if (delimiters.find(*pch) != delimiters.end())
                {
                if (start != pch)
                {
                std::string str(start, pch);
                result.push_back(str);
                }
                else
                {
                result.push_back("");
                }
                start = pch + 1;
                }
                }
                result.push_back(start);

                return result;
                }

                ...
                std::set<char> delims{'\'};

                std::vector<std::string> path = splitpath("C:\MyDirectory\MyFile.bat", delims);
                cout << path.back() << endl;





                share|improve this answer





















                • 2





                  There's no _splitpath in any of the includes on my machine.

                  – James Kanze
                  Dec 15 '11 at 13:22






                • 6





                  I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

                  – James Kanze
                  Dec 15 '11 at 13:49






                • 1





                  @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

                  – Synetech
                  Apr 4 '12 at 3:35






                • 1





                  @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

                  – James Kanze
                  Apr 4 '12 at 7:19






                • 3





                  @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

                  – Synetech
                  Apr 4 '12 at 19:05
















                25














                _splitpath should do what you need. You could of course do it manually but _splitpath handles all special cases as well.



                EDIT:



                As BillHoag mentioned it is recommended to use the more safe version of _splitpath called _splitpath_s when available.



                Or if you want something portable you could just do something like this



                std::vector<std::string> splitpath(
                const std::string& str
                , const std::set<char> delimiters)
                {
                std::vector<std::string> result;

                char const* pch = str.c_str();
                char const* start = pch;
                for(; *pch; ++pch)
                {
                if (delimiters.find(*pch) != delimiters.end())
                {
                if (start != pch)
                {
                std::string str(start, pch);
                result.push_back(str);
                }
                else
                {
                result.push_back("");
                }
                start = pch + 1;
                }
                }
                result.push_back(start);

                return result;
                }

                ...
                std::set<char> delims{'\'};

                std::vector<std::string> path = splitpath("C:\MyDirectory\MyFile.bat", delims);
                cout << path.back() << endl;





                share|improve this answer





















                • 2





                  There's no _splitpath in any of the includes on my machine.

                  – James Kanze
                  Dec 15 '11 at 13:22






                • 6





                  I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

                  – James Kanze
                  Dec 15 '11 at 13:49






                • 1





                  @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

                  – Synetech
                  Apr 4 '12 at 3:35






                • 1





                  @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

                  – James Kanze
                  Apr 4 '12 at 7:19






                • 3





                  @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

                  – Synetech
                  Apr 4 '12 at 19:05














                25












                25








                25







                _splitpath should do what you need. You could of course do it manually but _splitpath handles all special cases as well.



                EDIT:



                As BillHoag mentioned it is recommended to use the more safe version of _splitpath called _splitpath_s when available.



                Or if you want something portable you could just do something like this



                std::vector<std::string> splitpath(
                const std::string& str
                , const std::set<char> delimiters)
                {
                std::vector<std::string> result;

                char const* pch = str.c_str();
                char const* start = pch;
                for(; *pch; ++pch)
                {
                if (delimiters.find(*pch) != delimiters.end())
                {
                if (start != pch)
                {
                std::string str(start, pch);
                result.push_back(str);
                }
                else
                {
                result.push_back("");
                }
                start = pch + 1;
                }
                }
                result.push_back(start);

                return result;
                }

                ...
                std::set<char> delims{'\'};

                std::vector<std::string> path = splitpath("C:\MyDirectory\MyFile.bat", delims);
                cout << path.back() << endl;





                share|improve this answer















                _splitpath should do what you need. You could of course do it manually but _splitpath handles all special cases as well.



                EDIT:



                As BillHoag mentioned it is recommended to use the more safe version of _splitpath called _splitpath_s when available.



                Or if you want something portable you could just do something like this



                std::vector<std::string> splitpath(
                const std::string& str
                , const std::set<char> delimiters)
                {
                std::vector<std::string> result;

                char const* pch = str.c_str();
                char const* start = pch;
                for(; *pch; ++pch)
                {
                if (delimiters.find(*pch) != delimiters.end())
                {
                if (start != pch)
                {
                std::string str(start, pch);
                result.push_back(str);
                }
                else
                {
                result.push_back("");
                }
                start = pch + 1;
                }
                }
                result.push_back(start);

                return result;
                }

                ...
                std::set<char> delims{'\'};

                std::vector<std::string> path = splitpath("C:\MyDirectory\MyFile.bat", delims);
                cout << path.back() << endl;






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Apr 30 '16 at 13:44

























                answered Dec 15 '11 at 13:14









                AndersAnders

                30.1k64772




                30.1k64772








                • 2





                  There's no _splitpath in any of the includes on my machine.

                  – James Kanze
                  Dec 15 '11 at 13:22






                • 6





                  I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

                  – James Kanze
                  Dec 15 '11 at 13:49






                • 1





                  @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

                  – Synetech
                  Apr 4 '12 at 3:35






                • 1





                  @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

                  – James Kanze
                  Apr 4 '12 at 7:19






                • 3





                  @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

                  – Synetech
                  Apr 4 '12 at 19:05














                • 2





                  There's no _splitpath in any of the includes on my machine.

                  – James Kanze
                  Dec 15 '11 at 13:22






                • 6





                  I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

                  – James Kanze
                  Dec 15 '11 at 13:49






                • 1





                  @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

                  – Synetech
                  Apr 4 '12 at 3:35






                • 1





                  @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

                  – James Kanze
                  Apr 4 '12 at 7:19






                • 3





                  @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

                  – Synetech
                  Apr 4 '12 at 19:05








                2




                2





                There's no _splitpath in any of the includes on my machine.

                – James Kanze
                Dec 15 '11 at 13:22





                There's no _splitpath in any of the includes on my machine.

                – James Kanze
                Dec 15 '11 at 13:22




                6




                6





                I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

                – James Kanze
                Dec 15 '11 at 13:49





                I have Visual Studio, and g++, and Sun CC. Why should I use something non-standard when there are perfectly good portable solutions.

                – James Kanze
                Dec 15 '11 at 13:49




                1




                1





                @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

                – Synetech
                Apr 4 '12 at 3:35





                @James, the page linked to says it is in <stdlib.h>. As for portability, perhaps you can list some examples of “perfectly good portable solutions”?

                – Synetech
                Apr 4 '12 at 3:35




                1




                1





                @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

                – James Kanze
                Apr 4 '12 at 7:19





                @Synetech The page linked to describes a Microsoft extension, not <stdlib.h>. And the mot obvious portable solution is boost::filesystem.

                – James Kanze
                Apr 4 '12 at 7:19




                3




                3





                @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

                – Synetech
                Apr 4 '12 at 19:05





                @James, you don’t have _splitpath in the stdlib.h of your copy of VS? Then you may want to do a repair install of VS.

                – Synetech
                Apr 4 '12 at 19:05













                39














                A possible solution:



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

                // Remove directory if present.
                // Do this before extension removal incase directory has a period character.
                const size_t last_slash_idx = filename.find_last_of("\/");
                if (std::string::npos != last_slash_idx)
                {
                filename.erase(0, last_slash_idx + 1);
                }

                // Remove extension if present.
                const size_t period_idx = filename.rfind('.');
                if (std::string::npos != period_idx)
                {
                filename.erase(period_idx);
                }





                share|improve this answer


























                • the simplest is always the best!

                  – Jean-François Fabre
                  Apr 4 '18 at 15:12
















                39














                A possible solution:



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

                // Remove directory if present.
                // Do this before extension removal incase directory has a period character.
                const size_t last_slash_idx = filename.find_last_of("\/");
                if (std::string::npos != last_slash_idx)
                {
                filename.erase(0, last_slash_idx + 1);
                }

                // Remove extension if present.
                const size_t period_idx = filename.rfind('.');
                if (std::string::npos != period_idx)
                {
                filename.erase(period_idx);
                }





                share|improve this answer


























                • the simplest is always the best!

                  – Jean-François Fabre
                  Apr 4 '18 at 15:12














                39












                39








                39







                A possible solution:



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

                // Remove directory if present.
                // Do this before extension removal incase directory has a period character.
                const size_t last_slash_idx = filename.find_last_of("\/");
                if (std::string::npos != last_slash_idx)
                {
                filename.erase(0, last_slash_idx + 1);
                }

                // Remove extension if present.
                const size_t period_idx = filename.rfind('.');
                if (std::string::npos != period_idx)
                {
                filename.erase(period_idx);
                }





                share|improve this answer















                A possible solution:



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

                // Remove directory if present.
                // Do this before extension removal incase directory has a period character.
                const size_t last_slash_idx = filename.find_last_of("\/");
                if (std::string::npos != last_slash_idx)
                {
                filename.erase(0, last_slash_idx + 1);
                }

                // Remove extension if present.
                const size_t period_idx = filename.rfind('.');
                if (std::string::npos != period_idx)
                {
                filename.erase(period_idx);
                }






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 15 '11 at 13:46

























                answered Dec 15 '11 at 13:25









                hmjdhmjd

                102k13160217




                102k13160217













                • the simplest is always the best!

                  – Jean-François Fabre
                  Apr 4 '18 at 15:12



















                • the simplest is always the best!

                  – Jean-François Fabre
                  Apr 4 '18 at 15:12

















                the simplest is always the best!

                – Jean-François Fabre
                Apr 4 '18 at 15:12





                the simplest is always the best!

                – Jean-François Fabre
                Apr 4 '18 at 15:12











                37














                The simplest solution is to use something like boost::filesystem. If
                for some reason this isn't an option...



                Doing this correctly will require some system dependent code: under
                Windows, either '\' or '/' can be a path separator; under Unix,
                only '/' works, and under other systems, who knows. The obvious
                solution would be something like:



                std::string
                basename( std::string const& pathname )
                {
                return std::string(
                std::find_if( pathname.rbegin(), pathname.rend(),
                MatchPathSeparator() ).base(),
                pathname.end() );
                }


                , with MatchPathSeparator being defined in a system dependent header
                as either:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '/';
                }
                };


                for Unix, or:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '\' || ch == '/';
                }
                };


                for Windows (or something still different for some other unknown
                system).



                EDIT: I missed the fact that he also wanted to suppress the extention.
                For that, more of the same:



                std::string
                removeExtension( std::string const& filename )
                {
                std::string::const_reverse_iterator
                pivot
                = std::find( filename.rbegin(), filename.rend(), '.' );
                return pivot == filename.rend()
                ? filename
                : std::string( filename.begin(), pivot.base() - 1 );
                }


                The code is a little bit more complex, because in this case, the base of
                the reverse iterator is on the wrong side of where we want to cut.
                (Remember that the base of a reverse iterator is one behind the
                character the iterator points to.) And even this is a little dubious: I
                don't like the fact that it can return an empty string, for example.
                (If the only '.' is the first character of the filename, I'd argue
                that you should return the full filename. This would require a little
                bit of extra code to catch the special case.)
                }






                share|improve this answer





















                • 8





                  How about using string::find_last_of instead of manipulating reverse iterators?

                  – Luc Touraille
                  Dec 15 '11 at 14:04











                • @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

                  – James Kanze
                  Dec 15 '11 at 15:35











                • Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

                  – IInspectable
                  May 2 '17 at 10:39
















                37














                The simplest solution is to use something like boost::filesystem. If
                for some reason this isn't an option...



                Doing this correctly will require some system dependent code: under
                Windows, either '\' or '/' can be a path separator; under Unix,
                only '/' works, and under other systems, who knows. The obvious
                solution would be something like:



                std::string
                basename( std::string const& pathname )
                {
                return std::string(
                std::find_if( pathname.rbegin(), pathname.rend(),
                MatchPathSeparator() ).base(),
                pathname.end() );
                }


                , with MatchPathSeparator being defined in a system dependent header
                as either:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '/';
                }
                };


                for Unix, or:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '\' || ch == '/';
                }
                };


                for Windows (or something still different for some other unknown
                system).



                EDIT: I missed the fact that he also wanted to suppress the extention.
                For that, more of the same:



                std::string
                removeExtension( std::string const& filename )
                {
                std::string::const_reverse_iterator
                pivot
                = std::find( filename.rbegin(), filename.rend(), '.' );
                return pivot == filename.rend()
                ? filename
                : std::string( filename.begin(), pivot.base() - 1 );
                }


                The code is a little bit more complex, because in this case, the base of
                the reverse iterator is on the wrong side of where we want to cut.
                (Remember that the base of a reverse iterator is one behind the
                character the iterator points to.) And even this is a little dubious: I
                don't like the fact that it can return an empty string, for example.
                (If the only '.' is the first character of the filename, I'd argue
                that you should return the full filename. This would require a little
                bit of extra code to catch the special case.)
                }






                share|improve this answer





















                • 8





                  How about using string::find_last_of instead of manipulating reverse iterators?

                  – Luc Touraille
                  Dec 15 '11 at 14:04











                • @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

                  – James Kanze
                  Dec 15 '11 at 15:35











                • Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

                  – IInspectable
                  May 2 '17 at 10:39














                37












                37








                37







                The simplest solution is to use something like boost::filesystem. If
                for some reason this isn't an option...



                Doing this correctly will require some system dependent code: under
                Windows, either '\' or '/' can be a path separator; under Unix,
                only '/' works, and under other systems, who knows. The obvious
                solution would be something like:



                std::string
                basename( std::string const& pathname )
                {
                return std::string(
                std::find_if( pathname.rbegin(), pathname.rend(),
                MatchPathSeparator() ).base(),
                pathname.end() );
                }


                , with MatchPathSeparator being defined in a system dependent header
                as either:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '/';
                }
                };


                for Unix, or:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '\' || ch == '/';
                }
                };


                for Windows (or something still different for some other unknown
                system).



                EDIT: I missed the fact that he also wanted to suppress the extention.
                For that, more of the same:



                std::string
                removeExtension( std::string const& filename )
                {
                std::string::const_reverse_iterator
                pivot
                = std::find( filename.rbegin(), filename.rend(), '.' );
                return pivot == filename.rend()
                ? filename
                : std::string( filename.begin(), pivot.base() - 1 );
                }


                The code is a little bit more complex, because in this case, the base of
                the reverse iterator is on the wrong side of where we want to cut.
                (Remember that the base of a reverse iterator is one behind the
                character the iterator points to.) And even this is a little dubious: I
                don't like the fact that it can return an empty string, for example.
                (If the only '.' is the first character of the filename, I'd argue
                that you should return the full filename. This would require a little
                bit of extra code to catch the special case.)
                }






                share|improve this answer















                The simplest solution is to use something like boost::filesystem. If
                for some reason this isn't an option...



                Doing this correctly will require some system dependent code: under
                Windows, either '\' or '/' can be a path separator; under Unix,
                only '/' works, and under other systems, who knows. The obvious
                solution would be something like:



                std::string
                basename( std::string const& pathname )
                {
                return std::string(
                std::find_if( pathname.rbegin(), pathname.rend(),
                MatchPathSeparator() ).base(),
                pathname.end() );
                }


                , with MatchPathSeparator being defined in a system dependent header
                as either:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '/';
                }
                };


                for Unix, or:



                struct MatchPathSeparator
                {
                bool operator()( char ch ) const
                {
                return ch == '\' || ch == '/';
                }
                };


                for Windows (or something still different for some other unknown
                system).



                EDIT: I missed the fact that he also wanted to suppress the extention.
                For that, more of the same:



                std::string
                removeExtension( std::string const& filename )
                {
                std::string::const_reverse_iterator
                pivot
                = std::find( filename.rbegin(), filename.rend(), '.' );
                return pivot == filename.rend()
                ? filename
                : std::string( filename.begin(), pivot.base() - 1 );
                }


                The code is a little bit more complex, because in this case, the base of
                the reverse iterator is on the wrong side of where we want to cut.
                (Remember that the base of a reverse iterator is one behind the
                character the iterator points to.) And even this is a little dubious: I
                don't like the fact that it can return an empty string, for example.
                (If the only '.' is the first character of the filename, I'd argue
                that you should return the full filename. This would require a little
                bit of extra code to catch the special case.)
                }







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 15 '11 at 13:44

























                answered Dec 15 '11 at 13:30









                James KanzeJames Kanze

                129k9137278




                129k9137278








                • 8





                  How about using string::find_last_of instead of manipulating reverse iterators?

                  – Luc Touraille
                  Dec 15 '11 at 14:04











                • @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

                  – James Kanze
                  Dec 15 '11 at 15:35











                • Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

                  – IInspectable
                  May 2 '17 at 10:39














                • 8





                  How about using string::find_last_of instead of manipulating reverse iterators?

                  – Luc Touraille
                  Dec 15 '11 at 14:04











                • @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

                  – James Kanze
                  Dec 15 '11 at 15:35











                • Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

                  – IInspectable
                  May 2 '17 at 10:39








                8




                8





                How about using string::find_last_of instead of manipulating reverse iterators?

                – Luc Touraille
                Dec 15 '11 at 14:04





                How about using string::find_last_of instead of manipulating reverse iterators?

                – Luc Touraille
                Dec 15 '11 at 14:04













                @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

                – James Kanze
                Dec 15 '11 at 15:35





                @LucTouraille Why learn two ways of doing things when one will do? You'd need the reverse iterators for any container except string, so you have to learn them anyway. And having learned them, there's no reason to bother learning all of the bloated interface to std::string.

                – James Kanze
                Dec 15 '11 at 15:35













                Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

                – IInspectable
                May 2 '17 at 10:39





                Note: The <filesystem> header ships with Visual Studio 2015 and above, so you don't have to add a dependency on boost to use it.

                – IInspectable
                May 2 '17 at 10:39











                33














                The task is fairly simple as the base filename is just the part of the string starting at the last delimeter for folders:



                std::string base_filename = path.substr(path.find_last_of("/\") + 1)


                If the extension is to be removed as well the only thing to do is find the last . and take a substr to this point



                std::string::size_type const p(base_filename.find_last_of('.'));
                std::string file_without_extension = base_filename.substr(0, p);


                Perhaps there should be a check to cope with files solely consisting of extensions (ie .bashrc...)



                If you split this up into seperate functions you're flexible to reuse the single tasks:



                template<class T>
                T base_name(T const & path, T const & delims = "/\")
                {
                return path.substr(path.find_last_of(delims) + 1);
                }
                template<class T>
                T remove_extension(T const & filename)
                {
                typename T::size_type const p(filename.find_last_of('.'));
                return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
                }


                The code is templated to be able to use it with different std::basic_string instances (i.e. std::string & std::wstring...)



                The downside of the templation is the requirement to specify the template parameter if a const char * is passed to the functions.



                So you could either:



                A) Use only std::string instead of templating the code



                std::string base_name(std::string const & path)
                {
                return path.substr(path.find_last_of("/\") + 1);
                }


                B) Provide wrapping function using std::string (as intermediates which will likely be inlined / optimized away)



                inline std::string string_base_name(std::string const & path)
                {
                return base_name(path);
                }


                C) Specify the template parameter when calling with const char *.



                std::string base = base_name<std::string>("some/path/file.ext");


                Result



                std::string filepath = "C:\MyDirectory\MyFile.bat";
                std::cout << remove_extension(base_name(filepath)) << std::endl;


                Prints



                MyFile





                share|improve this answer
























                • In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

                  – avtomaton
                  Aug 27 '15 at 8:03











                • @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

                  – Pixelchemist
                  Aug 27 '15 at 9:14











                • I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

                  – avtomaton
                  Aug 27 '15 at 10:14











                • Very nice explanation. It enhances the structural understanding of the problem. Thanks

                  – hell_ical_vortex
                  May 18 '16 at 7:15
















                33














                The task is fairly simple as the base filename is just the part of the string starting at the last delimeter for folders:



                std::string base_filename = path.substr(path.find_last_of("/\") + 1)


                If the extension is to be removed as well the only thing to do is find the last . and take a substr to this point



                std::string::size_type const p(base_filename.find_last_of('.'));
                std::string file_without_extension = base_filename.substr(0, p);


                Perhaps there should be a check to cope with files solely consisting of extensions (ie .bashrc...)



                If you split this up into seperate functions you're flexible to reuse the single tasks:



                template<class T>
                T base_name(T const & path, T const & delims = "/\")
                {
                return path.substr(path.find_last_of(delims) + 1);
                }
                template<class T>
                T remove_extension(T const & filename)
                {
                typename T::size_type const p(filename.find_last_of('.'));
                return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
                }


                The code is templated to be able to use it with different std::basic_string instances (i.e. std::string & std::wstring...)



                The downside of the templation is the requirement to specify the template parameter if a const char * is passed to the functions.



                So you could either:



                A) Use only std::string instead of templating the code



                std::string base_name(std::string const & path)
                {
                return path.substr(path.find_last_of("/\") + 1);
                }


                B) Provide wrapping function using std::string (as intermediates which will likely be inlined / optimized away)



                inline std::string string_base_name(std::string const & path)
                {
                return base_name(path);
                }


                C) Specify the template parameter when calling with const char *.



                std::string base = base_name<std::string>("some/path/file.ext");


                Result



                std::string filepath = "C:\MyDirectory\MyFile.bat";
                std::cout << remove_extension(base_name(filepath)) << std::endl;


                Prints



                MyFile





                share|improve this answer
























                • In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

                  – avtomaton
                  Aug 27 '15 at 8:03











                • @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

                  – Pixelchemist
                  Aug 27 '15 at 9:14











                • I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

                  – avtomaton
                  Aug 27 '15 at 10:14











                • Very nice explanation. It enhances the structural understanding of the problem. Thanks

                  – hell_ical_vortex
                  May 18 '16 at 7:15














                33












                33








                33







                The task is fairly simple as the base filename is just the part of the string starting at the last delimeter for folders:



                std::string base_filename = path.substr(path.find_last_of("/\") + 1)


                If the extension is to be removed as well the only thing to do is find the last . and take a substr to this point



                std::string::size_type const p(base_filename.find_last_of('.'));
                std::string file_without_extension = base_filename.substr(0, p);


                Perhaps there should be a check to cope with files solely consisting of extensions (ie .bashrc...)



                If you split this up into seperate functions you're flexible to reuse the single tasks:



                template<class T>
                T base_name(T const & path, T const & delims = "/\")
                {
                return path.substr(path.find_last_of(delims) + 1);
                }
                template<class T>
                T remove_extension(T const & filename)
                {
                typename T::size_type const p(filename.find_last_of('.'));
                return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
                }


                The code is templated to be able to use it with different std::basic_string instances (i.e. std::string & std::wstring...)



                The downside of the templation is the requirement to specify the template parameter if a const char * is passed to the functions.



                So you could either:



                A) Use only std::string instead of templating the code



                std::string base_name(std::string const & path)
                {
                return path.substr(path.find_last_of("/\") + 1);
                }


                B) Provide wrapping function using std::string (as intermediates which will likely be inlined / optimized away)



                inline std::string string_base_name(std::string const & path)
                {
                return base_name(path);
                }


                C) Specify the template parameter when calling with const char *.



                std::string base = base_name<std::string>("some/path/file.ext");


                Result



                std::string filepath = "C:\MyDirectory\MyFile.bat";
                std::cout << remove_extension(base_name(filepath)) << std::endl;


                Prints



                MyFile





                share|improve this answer













                The task is fairly simple as the base filename is just the part of the string starting at the last delimeter for folders:



                std::string base_filename = path.substr(path.find_last_of("/\") + 1)


                If the extension is to be removed as well the only thing to do is find the last . and take a substr to this point



                std::string::size_type const p(base_filename.find_last_of('.'));
                std::string file_without_extension = base_filename.substr(0, p);


                Perhaps there should be a check to cope with files solely consisting of extensions (ie .bashrc...)



                If you split this up into seperate functions you're flexible to reuse the single tasks:



                template<class T>
                T base_name(T const & path, T const & delims = "/\")
                {
                return path.substr(path.find_last_of(delims) + 1);
                }
                template<class T>
                T remove_extension(T const & filename)
                {
                typename T::size_type const p(filename.find_last_of('.'));
                return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
                }


                The code is templated to be able to use it with different std::basic_string instances (i.e. std::string & std::wstring...)



                The downside of the templation is the requirement to specify the template parameter if a const char * is passed to the functions.



                So you could either:



                A) Use only std::string instead of templating the code



                std::string base_name(std::string const & path)
                {
                return path.substr(path.find_last_of("/\") + 1);
                }


                B) Provide wrapping function using std::string (as intermediates which will likely be inlined / optimized away)



                inline std::string string_base_name(std::string const & path)
                {
                return base_name(path);
                }


                C) Specify the template parameter when calling with const char *.



                std::string base = base_name<std::string>("some/path/file.ext");


                Result



                std::string filepath = "C:\MyDirectory\MyFile.bat";
                std::cout << remove_extension(base_name(filepath)) << std::endl;


                Prints



                MyFile






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jun 24 '14 at 12:44









                PixelchemistPixelchemist

                16.2k43162




                16.2k43162













                • In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

                  – avtomaton
                  Aug 27 '15 at 8:03











                • @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

                  – Pixelchemist
                  Aug 27 '15 at 9:14











                • I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

                  – avtomaton
                  Aug 27 '15 at 10:14











                • Very nice explanation. It enhances the structural understanding of the problem. Thanks

                  – hell_ical_vortex
                  May 18 '16 at 7:15



















                • In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

                  – avtomaton
                  Aug 27 '15 at 8:03











                • @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

                  – Pixelchemist
                  Aug 27 '15 at 9:14











                • I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

                  – avtomaton
                  Aug 27 '15 at 10:14











                • Very nice explanation. It enhances the structural understanding of the problem. Thanks

                  – hell_ical_vortex
                  May 18 '16 at 7:15

















                In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

                – avtomaton
                Aug 27 '15 at 8:03





                In this use case everything is OK (and original question is answered), but your extension remover is not perfect - it will fail if we pass there something like "/home/user/my.dir/myfile"

                – avtomaton
                Aug 27 '15 at 8:03













                @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

                – Pixelchemist
                Aug 27 '15 at 9:14





                @avtomaton The extension removing function should be used on a file name not a path. (Just apply base_name first.)

                – Pixelchemist
                Aug 27 '15 at 9:14













                I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

                – avtomaton
                Aug 27 '15 at 10:14





                I understand it (that's why I wrote that original question is answered and in this use-case everything is OK). Just wanted to point out to this issue for somebody who will try to use these snippets.

                – avtomaton
                Aug 27 '15 at 10:14













                Very nice explanation. It enhances the structural understanding of the problem. Thanks

                – hell_ical_vortex
                May 18 '16 at 7:15





                Very nice explanation. It enhances the structural understanding of the problem. Thanks

                – hell_ical_vortex
                May 18 '16 at 7:15











                12














                You can also use the shell Path APIs PathFindFileName, PathRemoveExtension. Probably worse than _splitpath for this particular problem, but those APIs are very useful for all kinds of path parsing jobs and they take UNC paths, forward slashes and other weird stuff into account.



                wstring filename = L"C:\MyDirectory\MyFile.bat";
                wchar_t* filepart = PathFindFileName(filename.c_str());
                PathRemoveExtension(filepart);


                http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx



                The drawback is that you have to link to shlwapi.lib, but I'm not really sure why that's a drawback.






                share|improve this answer
























                • My preferred solution for getting a filename from a path.

                  – mrt
                  May 12 '17 at 6:32
















                12














                You can also use the shell Path APIs PathFindFileName, PathRemoveExtension. Probably worse than _splitpath for this particular problem, but those APIs are very useful for all kinds of path parsing jobs and they take UNC paths, forward slashes and other weird stuff into account.



                wstring filename = L"C:\MyDirectory\MyFile.bat";
                wchar_t* filepart = PathFindFileName(filename.c_str());
                PathRemoveExtension(filepart);


                http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx



                The drawback is that you have to link to shlwapi.lib, but I'm not really sure why that's a drawback.






                share|improve this answer
























                • My preferred solution for getting a filename from a path.

                  – mrt
                  May 12 '17 at 6:32














                12












                12








                12







                You can also use the shell Path APIs PathFindFileName, PathRemoveExtension. Probably worse than _splitpath for this particular problem, but those APIs are very useful for all kinds of path parsing jobs and they take UNC paths, forward slashes and other weird stuff into account.



                wstring filename = L"C:\MyDirectory\MyFile.bat";
                wchar_t* filepart = PathFindFileName(filename.c_str());
                PathRemoveExtension(filepart);


                http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx



                The drawback is that you have to link to shlwapi.lib, but I'm not really sure why that's a drawback.






                share|improve this answer













                You can also use the shell Path APIs PathFindFileName, PathRemoveExtension. Probably worse than _splitpath for this particular problem, but those APIs are very useful for all kinds of path parsing jobs and they take UNC paths, forward slashes and other weird stuff into account.



                wstring filename = L"C:\MyDirectory\MyFile.bat";
                wchar_t* filepart = PathFindFileName(filename.c_str());
                PathRemoveExtension(filepart);


                http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx



                The drawback is that you have to link to shlwapi.lib, but I'm not really sure why that's a drawback.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Sep 13 '12 at 1:07









                SkrymsliSkrymsli

                2,70342332




                2,70342332













                • My preferred solution for getting a filename from a path.

                  – mrt
                  May 12 '17 at 6:32



















                • My preferred solution for getting a filename from a path.

                  – mrt
                  May 12 '17 at 6:32

















                My preferred solution for getting a filename from a path.

                – mrt
                May 12 '17 at 6:32





                My preferred solution for getting a filename from a path.

                – mrt
                May 12 '17 at 6:32











                11














                If you can use boost,



                #include <boost/filesystem.hpp>
                path p("C:\MyDirectory\MyFile.bat");
                string basename = p.filename().string();
                //or
                //string basename = path("C:\MyDirectory\MyFile.bat").filename().string();


                This is all.



                I recommend you to use boost library. Boost gives you a lot of conveniences when you work with C++. It supports almost all platforms.
                If you use Ubuntu, you can install boost library by only one line sudo apt-get install libboost-all-dev (ref. How to Install boost on Ubuntu?)






                share|improve this answer






























                  11














                  If you can use boost,



                  #include <boost/filesystem.hpp>
                  path p("C:\MyDirectory\MyFile.bat");
                  string basename = p.filename().string();
                  //or
                  //string basename = path("C:\MyDirectory\MyFile.bat").filename().string();


                  This is all.



                  I recommend you to use boost library. Boost gives you a lot of conveniences when you work with C++. It supports almost all platforms.
                  If you use Ubuntu, you can install boost library by only one line sudo apt-get install libboost-all-dev (ref. How to Install boost on Ubuntu?)






                  share|improve this answer




























                    11












                    11








                    11







                    If you can use boost,



                    #include <boost/filesystem.hpp>
                    path p("C:\MyDirectory\MyFile.bat");
                    string basename = p.filename().string();
                    //or
                    //string basename = path("C:\MyDirectory\MyFile.bat").filename().string();


                    This is all.



                    I recommend you to use boost library. Boost gives you a lot of conveniences when you work with C++. It supports almost all platforms.
                    If you use Ubuntu, you can install boost library by only one line sudo apt-get install libboost-all-dev (ref. How to Install boost on Ubuntu?)






                    share|improve this answer















                    If you can use boost,



                    #include <boost/filesystem.hpp>
                    path p("C:\MyDirectory\MyFile.bat");
                    string basename = p.filename().string();
                    //or
                    //string basename = path("C:\MyDirectory\MyFile.bat").filename().string();


                    This is all.



                    I recommend you to use boost library. Boost gives you a lot of conveniences when you work with C++. It supports almost all platforms.
                    If you use Ubuntu, you can install boost library by only one line sudo apt-get install libboost-all-dev (ref. How to Install boost on Ubuntu?)







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 23 '17 at 12:26









                    Community

                    11




                    11










                    answered Jul 22 '15 at 7:22









                    plhnplhn

                    2,46242435




                    2,46242435























                        10














                        Function:



                        #include <string>

                        std::string
                        basename(const std::string &filename)
                        {
                        if (filename.empty()) {
                        return {};
                        }

                        auto len = filename.length();
                        auto index = filename.find_last_of("/\");

                        if (index == std::string::npos) {
                        return filename;
                        }

                        if (index + 1 >= len) {

                        len--;
                        index = filename.substr(0, len).find_last_of("/\");

                        if (len == 0) {
                        return filename;
                        }

                        if (index == 0) {
                        return filename.substr(1, len - 1);
                        }

                        if (index == std::string::npos) {
                        return filename.substr(0, len);
                        }

                        return filename.substr(index + 1, len - index - 1);
                        }

                        return filename.substr(index + 1, len - index);
                        }


                        Tests:



                        #define CATCH_CONFIG_MAIN
                        #include <catch/catch.hpp>

                        TEST_CASE("basename")
                        {
                        CHECK(basename("") == "");
                        CHECK(basename("no_path") == "no_path");
                        CHECK(basename("with.ext") == "with.ext");
                        CHECK(basename("/no_filename/") == "no_filename");
                        CHECK(basename("no_filename/") == "no_filename");
                        CHECK(basename("/no/filename/") == "filename");
                        CHECK(basename("/absolute/file.ext") == "file.ext");
                        CHECK(basename("../relative/file.ext") == "file.ext");
                        CHECK(basename("/") == "/");
                        CHECK(basename("c:\windows\path.ext") == "path.ext");
                        CHECK(basename("c:\windows\no_filename\") == "no_filename");
                        }





                        share|improve this answer






























                          10














                          Function:



                          #include <string>

                          std::string
                          basename(const std::string &filename)
                          {
                          if (filename.empty()) {
                          return {};
                          }

                          auto len = filename.length();
                          auto index = filename.find_last_of("/\");

                          if (index == std::string::npos) {
                          return filename;
                          }

                          if (index + 1 >= len) {

                          len--;
                          index = filename.substr(0, len).find_last_of("/\");

                          if (len == 0) {
                          return filename;
                          }

                          if (index == 0) {
                          return filename.substr(1, len - 1);
                          }

                          if (index == std::string::npos) {
                          return filename.substr(0, len);
                          }

                          return filename.substr(index + 1, len - index - 1);
                          }

                          return filename.substr(index + 1, len - index);
                          }


                          Tests:



                          #define CATCH_CONFIG_MAIN
                          #include <catch/catch.hpp>

                          TEST_CASE("basename")
                          {
                          CHECK(basename("") == "");
                          CHECK(basename("no_path") == "no_path");
                          CHECK(basename("with.ext") == "with.ext");
                          CHECK(basename("/no_filename/") == "no_filename");
                          CHECK(basename("no_filename/") == "no_filename");
                          CHECK(basename("/no/filename/") == "filename");
                          CHECK(basename("/absolute/file.ext") == "file.ext");
                          CHECK(basename("../relative/file.ext") == "file.ext");
                          CHECK(basename("/") == "/");
                          CHECK(basename("c:\windows\path.ext") == "path.ext");
                          CHECK(basename("c:\windows\no_filename\") == "no_filename");
                          }





                          share|improve this answer




























                            10












                            10








                            10







                            Function:



                            #include <string>

                            std::string
                            basename(const std::string &filename)
                            {
                            if (filename.empty()) {
                            return {};
                            }

                            auto len = filename.length();
                            auto index = filename.find_last_of("/\");

                            if (index == std::string::npos) {
                            return filename;
                            }

                            if (index + 1 >= len) {

                            len--;
                            index = filename.substr(0, len).find_last_of("/\");

                            if (len == 0) {
                            return filename;
                            }

                            if (index == 0) {
                            return filename.substr(1, len - 1);
                            }

                            if (index == std::string::npos) {
                            return filename.substr(0, len);
                            }

                            return filename.substr(index + 1, len - index - 1);
                            }

                            return filename.substr(index + 1, len - index);
                            }


                            Tests:



                            #define CATCH_CONFIG_MAIN
                            #include <catch/catch.hpp>

                            TEST_CASE("basename")
                            {
                            CHECK(basename("") == "");
                            CHECK(basename("no_path") == "no_path");
                            CHECK(basename("with.ext") == "with.ext");
                            CHECK(basename("/no_filename/") == "no_filename");
                            CHECK(basename("no_filename/") == "no_filename");
                            CHECK(basename("/no/filename/") == "filename");
                            CHECK(basename("/absolute/file.ext") == "file.ext");
                            CHECK(basename("../relative/file.ext") == "file.ext");
                            CHECK(basename("/") == "/");
                            CHECK(basename("c:\windows\path.ext") == "path.ext");
                            CHECK(basename("c:\windows\no_filename\") == "no_filename");
                            }





                            share|improve this answer















                            Function:



                            #include <string>

                            std::string
                            basename(const std::string &filename)
                            {
                            if (filename.empty()) {
                            return {};
                            }

                            auto len = filename.length();
                            auto index = filename.find_last_of("/\");

                            if (index == std::string::npos) {
                            return filename;
                            }

                            if (index + 1 >= len) {

                            len--;
                            index = filename.substr(0, len).find_last_of("/\");

                            if (len == 0) {
                            return filename;
                            }

                            if (index == 0) {
                            return filename.substr(1, len - 1);
                            }

                            if (index == std::string::npos) {
                            return filename.substr(0, len);
                            }

                            return filename.substr(index + 1, len - index - 1);
                            }

                            return filename.substr(index + 1, len - index);
                            }


                            Tests:



                            #define CATCH_CONFIG_MAIN
                            #include <catch/catch.hpp>

                            TEST_CASE("basename")
                            {
                            CHECK(basename("") == "");
                            CHECK(basename("no_path") == "no_path");
                            CHECK(basename("with.ext") == "with.ext");
                            CHECK(basename("/no_filename/") == "no_filename");
                            CHECK(basename("no_filename/") == "no_filename");
                            CHECK(basename("/no/filename/") == "filename");
                            CHECK(basename("/absolute/file.ext") == "file.ext");
                            CHECK(basename("../relative/file.ext") == "file.ext");
                            CHECK(basename("/") == "/");
                            CHECK(basename("c:\windows\path.ext") == "path.ext");
                            CHECK(basename("c:\windows\no_filename\") == "no_filename");
                            }






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Apr 7 '17 at 17:41

























                            answered Apr 7 '17 at 17:25









                            Rian QuinnRian Quinn

                            35537




                            35537























                                7














                                From C++ Docs - string::find_last_of



                                #include <iostream>       // std::cout
                                #include <string> // std::string

                                void SplitFilename (const std::string& str) {
                                std::cout << "Splitting: " << str << 'n';
                                unsigned found = str.find_last_of("/\");
                                std::cout << " path: " << str.substr(0,found) << 'n';
                                std::cout << " file: " << str.substr(found+1) << 'n';
                                }

                                int main () {
                                std::string str1 ("/usr/bin/man");
                                std::string str2 ("c:\windows\winhelp.exe");

                                SplitFilename (str1);
                                SplitFilename (str2);

                                return 0;
                                }


                                Outputs:



                                Splitting: /usr/bin/man
                                path: /usr/bin
                                file: man
                                Splitting: c:windowswinhelp.exe
                                path: c:windows
                                file: winhelp.exe





                                share|improve this answer
























                                • Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

                                  – congusbongus
                                  Mar 14 '16 at 23:53











                                • @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

                                  – jave.web
                                  Mar 15 '16 at 11:05













                                • @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

                                  – winux
                                  Sep 22 '16 at 8:09













                                • @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

                                  – jave.web
                                  Sep 23 '16 at 13:07











                                • @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

                                  – jave.web
                                  Sep 23 '16 at 13:07


















                                7














                                From C++ Docs - string::find_last_of



                                #include <iostream>       // std::cout
                                #include <string> // std::string

                                void SplitFilename (const std::string& str) {
                                std::cout << "Splitting: " << str << 'n';
                                unsigned found = str.find_last_of("/\");
                                std::cout << " path: " << str.substr(0,found) << 'n';
                                std::cout << " file: " << str.substr(found+1) << 'n';
                                }

                                int main () {
                                std::string str1 ("/usr/bin/man");
                                std::string str2 ("c:\windows\winhelp.exe");

                                SplitFilename (str1);
                                SplitFilename (str2);

                                return 0;
                                }


                                Outputs:



                                Splitting: /usr/bin/man
                                path: /usr/bin
                                file: man
                                Splitting: c:windowswinhelp.exe
                                path: c:windows
                                file: winhelp.exe





                                share|improve this answer
























                                • Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

                                  – congusbongus
                                  Mar 14 '16 at 23:53











                                • @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

                                  – jave.web
                                  Mar 15 '16 at 11:05













                                • @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

                                  – winux
                                  Sep 22 '16 at 8:09













                                • @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

                                  – jave.web
                                  Sep 23 '16 at 13:07











                                • @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

                                  – jave.web
                                  Sep 23 '16 at 13:07
















                                7












                                7








                                7







                                From C++ Docs - string::find_last_of



                                #include <iostream>       // std::cout
                                #include <string> // std::string

                                void SplitFilename (const std::string& str) {
                                std::cout << "Splitting: " << str << 'n';
                                unsigned found = str.find_last_of("/\");
                                std::cout << " path: " << str.substr(0,found) << 'n';
                                std::cout << " file: " << str.substr(found+1) << 'n';
                                }

                                int main () {
                                std::string str1 ("/usr/bin/man");
                                std::string str2 ("c:\windows\winhelp.exe");

                                SplitFilename (str1);
                                SplitFilename (str2);

                                return 0;
                                }


                                Outputs:



                                Splitting: /usr/bin/man
                                path: /usr/bin
                                file: man
                                Splitting: c:windowswinhelp.exe
                                path: c:windows
                                file: winhelp.exe





                                share|improve this answer













                                From C++ Docs - string::find_last_of



                                #include <iostream>       // std::cout
                                #include <string> // std::string

                                void SplitFilename (const std::string& str) {
                                std::cout << "Splitting: " << str << 'n';
                                unsigned found = str.find_last_of("/\");
                                std::cout << " path: " << str.substr(0,found) << 'n';
                                std::cout << " file: " << str.substr(found+1) << 'n';
                                }

                                int main () {
                                std::string str1 ("/usr/bin/man");
                                std::string str2 ("c:\windows\winhelp.exe");

                                SplitFilename (str1);
                                SplitFilename (str2);

                                return 0;
                                }


                                Outputs:



                                Splitting: /usr/bin/man
                                path: /usr/bin
                                file: man
                                Splitting: c:windowswinhelp.exe
                                path: c:windows
                                file: winhelp.exe






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Apr 2 '15 at 3:42









                                jave.webjave.web

                                6,38895376




                                6,38895376













                                • Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

                                  – congusbongus
                                  Mar 14 '16 at 23:53











                                • @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

                                  – jave.web
                                  Mar 15 '16 at 11:05













                                • @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

                                  – winux
                                  Sep 22 '16 at 8:09













                                • @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

                                  – jave.web
                                  Sep 23 '16 at 13:07











                                • @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

                                  – jave.web
                                  Sep 23 '16 at 13:07





















                                • Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

                                  – congusbongus
                                  Mar 14 '16 at 23:53











                                • @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

                                  – jave.web
                                  Mar 15 '16 at 11:05













                                • @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

                                  – winux
                                  Sep 22 '16 at 8:09













                                • @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

                                  – jave.web
                                  Sep 23 '16 at 13:07











                                • @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

                                  – jave.web
                                  Sep 23 '16 at 13:07



















                                Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

                                – congusbongus
                                Mar 14 '16 at 23:53





                                Don't forget (and to handle) that find_last_of returns string::npos if nothing was found.

                                – congusbongus
                                Mar 14 '16 at 23:53













                                @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

                                – jave.web
                                Mar 15 '16 at 11:05







                                @congusbongus True, but there is no sense of splitting the file path when it is just a file name (without path) :)

                                – jave.web
                                Mar 15 '16 at 11:05















                                @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

                                – winux
                                Sep 22 '16 at 8:09







                                @jave.web It does make sense and MUST handle returns 'string::npos'. Implementing a function for this should be able to handle different inputs including "just filename". Otherwise, it will be useless if its buggy in actual implementation.

                                – winux
                                Sep 22 '16 at 8:09















                                @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

                                – jave.web
                                Sep 23 '16 at 13:07





                                @winux This considers already valid PATHS... If you don't trust the input, you should, of course, validate the path first.

                                – jave.web
                                Sep 23 '16 at 13:07













                                @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

                                – jave.web
                                Sep 23 '16 at 13:07







                                @winux Anyway the check for string::npos does not need to be done because of the way how this and string::substr are implemented. a) string::npos is passed as "length" => substr has documented behaviour of reading all until end. b) substr is given "string::npos + 1" and no length: string::npos is documented to have a value of -1, so that evaluates to 0 => start of the string and lengths' default value for substr is the npos => works on "just filename" too cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos

                                – jave.web
                                Sep 23 '16 at 13:07













                                6














                                The Simplest way in cpp17 is:



                                use the #include experimental/filesystem and filename() for filename with extension and stem() without extension.



                                   #include <iostream>
                                #include <experimental/filesystem>
                                namespace fs = std::experimental::filesystem;

                                int main()
                                {
                                string filename = "C:\MyDirectory\MyFile.bat";

                                std::cout << fs::path(filename).filename() << 'n'
                                << fs::path(filename).stem() << 'n'
                                << fs::path("/foo/bar.txt").filename() << 'n'
                                << fs::path("/foo/bar.txt").stem() << 'n'
                                << fs::path("/foo/.bar").filename() << 'n'
                                << fs::path("/foo/bar/").filename() << 'n'
                                << fs::path("/foo/.").filename() << 'n'
                                << fs::path("/foo/..").filename() << 'n'
                                << fs::path(".").filename() << 'n'
                                << fs::path("..").filename() << 'n'
                                << fs::path("/").filename() << 'n';
                                }


                                output:



                                MyFile.bat
                                MyFile
                                "bar.txt"
                                ".bar"
                                "."
                                "."
                                ".."
                                "."
                                ".."
                                "/"


                                Ref: cppreference






                                share|improve this answer






























                                  6














                                  The Simplest way in cpp17 is:



                                  use the #include experimental/filesystem and filename() for filename with extension and stem() without extension.



                                     #include <iostream>
                                  #include <experimental/filesystem>
                                  namespace fs = std::experimental::filesystem;

                                  int main()
                                  {
                                  string filename = "C:\MyDirectory\MyFile.bat";

                                  std::cout << fs::path(filename).filename() << 'n'
                                  << fs::path(filename).stem() << 'n'
                                  << fs::path("/foo/bar.txt").filename() << 'n'
                                  << fs::path("/foo/bar.txt").stem() << 'n'
                                  << fs::path("/foo/.bar").filename() << 'n'
                                  << fs::path("/foo/bar/").filename() << 'n'
                                  << fs::path("/foo/.").filename() << 'n'
                                  << fs::path("/foo/..").filename() << 'n'
                                  << fs::path(".").filename() << 'n'
                                  << fs::path("..").filename() << 'n'
                                  << fs::path("/").filename() << 'n';
                                  }


                                  output:



                                  MyFile.bat
                                  MyFile
                                  "bar.txt"
                                  ".bar"
                                  "."
                                  "."
                                  ".."
                                  "."
                                  ".."
                                  "/"


                                  Ref: cppreference






                                  share|improve this answer




























                                    6












                                    6








                                    6







                                    The Simplest way in cpp17 is:



                                    use the #include experimental/filesystem and filename() for filename with extension and stem() without extension.



                                       #include <iostream>
                                    #include <experimental/filesystem>
                                    namespace fs = std::experimental::filesystem;

                                    int main()
                                    {
                                    string filename = "C:\MyDirectory\MyFile.bat";

                                    std::cout << fs::path(filename).filename() << 'n'
                                    << fs::path(filename).stem() << 'n'
                                    << fs::path("/foo/bar.txt").filename() << 'n'
                                    << fs::path("/foo/bar.txt").stem() << 'n'
                                    << fs::path("/foo/.bar").filename() << 'n'
                                    << fs::path("/foo/bar/").filename() << 'n'
                                    << fs::path("/foo/.").filename() << 'n'
                                    << fs::path("/foo/..").filename() << 'n'
                                    << fs::path(".").filename() << 'n'
                                    << fs::path("..").filename() << 'n'
                                    << fs::path("/").filename() << 'n';
                                    }


                                    output:



                                    MyFile.bat
                                    MyFile
                                    "bar.txt"
                                    ".bar"
                                    "."
                                    "."
                                    ".."
                                    "."
                                    ".."
                                    "/"


                                    Ref: cppreference






                                    share|improve this answer















                                    The Simplest way in cpp17 is:



                                    use the #include experimental/filesystem and filename() for filename with extension and stem() without extension.



                                       #include <iostream>
                                    #include <experimental/filesystem>
                                    namespace fs = std::experimental::filesystem;

                                    int main()
                                    {
                                    string filename = "C:\MyDirectory\MyFile.bat";

                                    std::cout << fs::path(filename).filename() << 'n'
                                    << fs::path(filename).stem() << 'n'
                                    << fs::path("/foo/bar.txt").filename() << 'n'
                                    << fs::path("/foo/bar.txt").stem() << 'n'
                                    << fs::path("/foo/.bar").filename() << 'n'
                                    << fs::path("/foo/bar/").filename() << 'n'
                                    << fs::path("/foo/.").filename() << 'n'
                                    << fs::path("/foo/..").filename() << 'n'
                                    << fs::path(".").filename() << 'n'
                                    << fs::path("..").filename() << 'n'
                                    << fs::path("/").filename() << 'n';
                                    }


                                    output:



                                    MyFile.bat
                                    MyFile
                                    "bar.txt"
                                    ".bar"
                                    "."
                                    "."
                                    ".."
                                    "."
                                    ".."
                                    "/"


                                    Ref: cppreference







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Jan 30 '18 at 10:11

























                                    answered Jan 30 '18 at 9:37









                                    eliasetmeliasetm

                                    33227




                                    33227























                                        5














                                        C++11 variant (inspired by James Kanze's version) with uniform initialization and anonymous inline lambda.



                                        std::string basename(const std::string& pathname)
                                        {
                                        return {std::find_if(pathname.rbegin(), pathname.rend(),
                                        (char c) { return c == '/'; }).base(),
                                        pathname.end()};
                                        }


                                        It does not remove the file extension though.






                                        share|improve this answer


























                                        • Short and sweet, although it only works with non-Windows paths.

                                          – Volomike
                                          Mar 5 '16 at 18:33











                                        • you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

                                          – ziomq1991
                                          Apr 19 '16 at 9:57











                                        • To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

                                          – Gidfiddle
                                          Oct 27 '17 at 6:14
















                                        5














                                        C++11 variant (inspired by James Kanze's version) with uniform initialization and anonymous inline lambda.



                                        std::string basename(const std::string& pathname)
                                        {
                                        return {std::find_if(pathname.rbegin(), pathname.rend(),
                                        (char c) { return c == '/'; }).base(),
                                        pathname.end()};
                                        }


                                        It does not remove the file extension though.






                                        share|improve this answer


























                                        • Short and sweet, although it only works with non-Windows paths.

                                          – Volomike
                                          Mar 5 '16 at 18:33











                                        • you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

                                          – ziomq1991
                                          Apr 19 '16 at 9:57











                                        • To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

                                          – Gidfiddle
                                          Oct 27 '17 at 6:14














                                        5












                                        5








                                        5







                                        C++11 variant (inspired by James Kanze's version) with uniform initialization and anonymous inline lambda.



                                        std::string basename(const std::string& pathname)
                                        {
                                        return {std::find_if(pathname.rbegin(), pathname.rend(),
                                        (char c) { return c == '/'; }).base(),
                                        pathname.end()};
                                        }


                                        It does not remove the file extension though.






                                        share|improve this answer















                                        C++11 variant (inspired by James Kanze's version) with uniform initialization and anonymous inline lambda.



                                        std::string basename(const std::string& pathname)
                                        {
                                        return {std::find_if(pathname.rbegin(), pathname.rend(),
                                        (char c) { return c == '/'; }).base(),
                                        pathname.end()};
                                        }


                                        It does not remove the file extension though.







                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Mar 5 '16 at 18:34









                                        Volomike

                                        13.7k1881153




                                        13.7k1881153










                                        answered Oct 17 '13 at 23:41









                                        alvekoalveko

                                        95621115




                                        95621115













                                        • Short and sweet, although it only works with non-Windows paths.

                                          – Volomike
                                          Mar 5 '16 at 18:33











                                        • you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

                                          – ziomq1991
                                          Apr 19 '16 at 9:57











                                        • To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

                                          – Gidfiddle
                                          Oct 27 '17 at 6:14



















                                        • Short and sweet, although it only works with non-Windows paths.

                                          – Volomike
                                          Mar 5 '16 at 18:33











                                        • you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

                                          – ziomq1991
                                          Apr 19 '16 at 9:57











                                        • To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

                                          – Gidfiddle
                                          Oct 27 '17 at 6:14

















                                        Short and sweet, although it only works with non-Windows paths.

                                        – Volomike
                                        Mar 5 '16 at 18:33





                                        Short and sweet, although it only works with non-Windows paths.

                                        – Volomike
                                        Mar 5 '16 at 18:33













                                        you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

                                        – ziomq1991
                                        Apr 19 '16 at 9:57





                                        you can always change lambda return to return c == '/' || c == '\'; to make it works on windows

                                        – ziomq1991
                                        Apr 19 '16 at 9:57













                                        To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

                                        – Gidfiddle
                                        Oct 27 '17 at 6:14





                                        To handle paths such as "", "///", and "dir1/dir2/", add the following code before the return statement above (cf. POSIX basename()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());

                                        – Gidfiddle
                                        Oct 27 '17 at 6:14











                                        4














                                        this is the only thing that actually finally worked for me:



                                        #include "Shlwapi.h"

                                        CString some_string = "c:\path\hello.txt";
                                        LPCSTR file_path = some_string.GetString();
                                        LPCSTR filepart_c = PathFindFileName(file_path);
                                        LPSTR filepart = LPSTR(filepart_c);
                                        PathRemoveExtension(filepart);


                                        pretty much what Skrymsli suggested but doesn't work with wchar_t*,
                                        VS Enterprise 2015



                                        _splitpath worked as well, but I don't like having to guess at how many char[?] characters I'm going to need; some people probably need this control, i guess.



                                        CString c_model_name = "c:\path\hello.txt";
                                        char drive[200];
                                        char dir[200];
                                        char name[200];
                                        char ext[200];
                                        _splitpath(c_model_name, drive, dir, name, ext);


                                        I don't believe any includes were needed for _splitpath. No external libraries (like boost) were needed for either of these solutions.






                                        share|improve this answer




























                                          4














                                          this is the only thing that actually finally worked for me:



                                          #include "Shlwapi.h"

                                          CString some_string = "c:\path\hello.txt";
                                          LPCSTR file_path = some_string.GetString();
                                          LPCSTR filepart_c = PathFindFileName(file_path);
                                          LPSTR filepart = LPSTR(filepart_c);
                                          PathRemoveExtension(filepart);


                                          pretty much what Skrymsli suggested but doesn't work with wchar_t*,
                                          VS Enterprise 2015



                                          _splitpath worked as well, but I don't like having to guess at how many char[?] characters I'm going to need; some people probably need this control, i guess.



                                          CString c_model_name = "c:\path\hello.txt";
                                          char drive[200];
                                          char dir[200];
                                          char name[200];
                                          char ext[200];
                                          _splitpath(c_model_name, drive, dir, name, ext);


                                          I don't believe any includes were needed for _splitpath. No external libraries (like boost) were needed for either of these solutions.






                                          share|improve this answer


























                                            4












                                            4








                                            4







                                            this is the only thing that actually finally worked for me:



                                            #include "Shlwapi.h"

                                            CString some_string = "c:\path\hello.txt";
                                            LPCSTR file_path = some_string.GetString();
                                            LPCSTR filepart_c = PathFindFileName(file_path);
                                            LPSTR filepart = LPSTR(filepart_c);
                                            PathRemoveExtension(filepart);


                                            pretty much what Skrymsli suggested but doesn't work with wchar_t*,
                                            VS Enterprise 2015



                                            _splitpath worked as well, but I don't like having to guess at how many char[?] characters I'm going to need; some people probably need this control, i guess.



                                            CString c_model_name = "c:\path\hello.txt";
                                            char drive[200];
                                            char dir[200];
                                            char name[200];
                                            char ext[200];
                                            _splitpath(c_model_name, drive, dir, name, ext);


                                            I don't believe any includes were needed for _splitpath. No external libraries (like boost) were needed for either of these solutions.






                                            share|improve this answer













                                            this is the only thing that actually finally worked for me:



                                            #include "Shlwapi.h"

                                            CString some_string = "c:\path\hello.txt";
                                            LPCSTR file_path = some_string.GetString();
                                            LPCSTR filepart_c = PathFindFileName(file_path);
                                            LPSTR filepart = LPSTR(filepart_c);
                                            PathRemoveExtension(filepart);


                                            pretty much what Skrymsli suggested but doesn't work with wchar_t*,
                                            VS Enterprise 2015



                                            _splitpath worked as well, but I don't like having to guess at how many char[?] characters I'm going to need; some people probably need this control, i guess.



                                            CString c_model_name = "c:\path\hello.txt";
                                            char drive[200];
                                            char dir[200];
                                            char name[200];
                                            char ext[200];
                                            _splitpath(c_model_name, drive, dir, name, ext);


                                            I don't believe any includes were needed for _splitpath. No external libraries (like boost) were needed for either of these solutions.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Mar 24 '16 at 16:44









                                            FractalFractal

                                            5012823




                                            5012823























                                                3














                                                I would do it by...



                                                Search backwards from the end of the string until you find the first backslash/forward slash.



                                                Then search backwards again from the end of the string until you find the first dot (.)



                                                You then have the start and end of the file name.



                                                Simples...






                                                share|improve this answer


























                                                • Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

                                                  – James Kanze
                                                  Dec 15 '11 at 13:32











                                                • Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

                                                  – TomP89
                                                  Dec 15 '11 at 13:48











                                                • You still have to find the last dot, not the first. (Reverse iterators are your friend!)

                                                  – James Kanze
                                                  Dec 15 '11 at 13:56











                                                • Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

                                                  – TomP89
                                                  Dec 15 '11 at 13:57











                                                • Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

                                                  – James Kanze
                                                  Dec 15 '11 at 14:02
















                                                3














                                                I would do it by...



                                                Search backwards from the end of the string until you find the first backslash/forward slash.



                                                Then search backwards again from the end of the string until you find the first dot (.)



                                                You then have the start and end of the file name.



                                                Simples...






                                                share|improve this answer


























                                                • Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

                                                  – James Kanze
                                                  Dec 15 '11 at 13:32











                                                • Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

                                                  – TomP89
                                                  Dec 15 '11 at 13:48











                                                • You still have to find the last dot, not the first. (Reverse iterators are your friend!)

                                                  – James Kanze
                                                  Dec 15 '11 at 13:56











                                                • Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

                                                  – TomP89
                                                  Dec 15 '11 at 13:57











                                                • Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

                                                  – James Kanze
                                                  Dec 15 '11 at 14:02














                                                3












                                                3








                                                3







                                                I would do it by...



                                                Search backwards from the end of the string until you find the first backslash/forward slash.



                                                Then search backwards again from the end of the string until you find the first dot (.)



                                                You then have the start and end of the file name.



                                                Simples...






                                                share|improve this answer















                                                I would do it by...



                                                Search backwards from the end of the string until you find the first backslash/forward slash.



                                                Then search backwards again from the end of the string until you find the first dot (.)



                                                You then have the start and end of the file name.



                                                Simples...







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Dec 15 '11 at 13:58

























                                                answered Dec 15 '11 at 13:23









                                                TomP89TomP89

                                                1,0421926




                                                1,0421926













                                                • Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

                                                  – James Kanze
                                                  Dec 15 '11 at 13:32











                                                • Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

                                                  – TomP89
                                                  Dec 15 '11 at 13:48











                                                • You still have to find the last dot, not the first. (Reverse iterators are your friend!)

                                                  – James Kanze
                                                  Dec 15 '11 at 13:56











                                                • Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

                                                  – TomP89
                                                  Dec 15 '11 at 13:57











                                                • Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

                                                  – James Kanze
                                                  Dec 15 '11 at 14:02



















                                                • Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

                                                  – James Kanze
                                                  Dec 15 '11 at 13:32











                                                • Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

                                                  – TomP89
                                                  Dec 15 '11 at 13:48











                                                • You still have to find the last dot, not the first. (Reverse iterators are your friend!)

                                                  – James Kanze
                                                  Dec 15 '11 at 13:56











                                                • Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

                                                  – TomP89
                                                  Dec 15 '11 at 13:57











                                                • Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

                                                  – James Kanze
                                                  Dec 15 '11 at 14:02

















                                                Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

                                                – James Kanze
                                                Dec 15 '11 at 13:32





                                                Which doesn't work for any system I know. (The one system which accepts '\' as a path separator also uses '/', so you need to match either.) And I'm not sure what you'd be looking forward for.

                                                – James Kanze
                                                Dec 15 '11 at 13:32













                                                Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

                                                – TomP89
                                                Dec 15 '11 at 13:48





                                                Okay so modify it to match either, no biggy. And looking forward for the first dot (.)

                                                – TomP89
                                                Dec 15 '11 at 13:48













                                                You still have to find the last dot, not the first. (Reverse iterators are your friend!)

                                                – James Kanze
                                                Dec 15 '11 at 13:56





                                                You still have to find the last dot, not the first. (Reverse iterators are your friend!)

                                                – James Kanze
                                                Dec 15 '11 at 13:56













                                                Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

                                                – TomP89
                                                Dec 15 '11 at 13:57





                                                Ah yes, good point. So for a file.ext.ext then you would want to extract file.ext wouldn't you. :)

                                                – TomP89
                                                Dec 15 '11 at 13:57













                                                Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

                                                – James Kanze
                                                Dec 15 '11 at 14:02





                                                Presumably. That's the usual convention, in any case: my.source.cpp gets compiled to my.source.obj, for example (with the extension .cpp replaced with .obj).

                                                – James Kanze
                                                Dec 15 '11 at 14:02











                                                3














                                                The boost filesystem library is also available as the experimental/filesystem library and was merged into ISO C++ for C++17. You can use it like this:



                                                #include <iostream>
                                                #include <experimental/filesystem>

                                                namespace fs = std::experimental::filesystem;

                                                int main () {
                                                std::cout << fs::path("/foo/bar.txt").filename() << 'n'
                                                }


                                                Output:



                                                "bar.txt"


                                                It also works for std::string objects.






                                                share|improve this answer


























                                                • Note that the later answer of @eliastem is the same...

                                                  – Adam Erickson
                                                  Jul 4 '18 at 1:25
















                                                3














                                                The boost filesystem library is also available as the experimental/filesystem library and was merged into ISO C++ for C++17. You can use it like this:



                                                #include <iostream>
                                                #include <experimental/filesystem>

                                                namespace fs = std::experimental::filesystem;

                                                int main () {
                                                std::cout << fs::path("/foo/bar.txt").filename() << 'n'
                                                }


                                                Output:



                                                "bar.txt"


                                                It also works for std::string objects.






                                                share|improve this answer


























                                                • Note that the later answer of @eliastem is the same...

                                                  – Adam Erickson
                                                  Jul 4 '18 at 1:25














                                                3












                                                3








                                                3







                                                The boost filesystem library is also available as the experimental/filesystem library and was merged into ISO C++ for C++17. You can use it like this:



                                                #include <iostream>
                                                #include <experimental/filesystem>

                                                namespace fs = std::experimental::filesystem;

                                                int main () {
                                                std::cout << fs::path("/foo/bar.txt").filename() << 'n'
                                                }


                                                Output:



                                                "bar.txt"


                                                It also works for std::string objects.






                                                share|improve this answer















                                                The boost filesystem library is also available as the experimental/filesystem library and was merged into ISO C++ for C++17. You can use it like this:



                                                #include <iostream>
                                                #include <experimental/filesystem>

                                                namespace fs = std::experimental::filesystem;

                                                int main () {
                                                std::cout << fs::path("/foo/bar.txt").filename() << 'n'
                                                }


                                                Output:



                                                "bar.txt"


                                                It also works for std::string objects.







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Jul 4 '18 at 1:23

























                                                answered Dec 1 '17 at 19:00









                                                Adam EricksonAdam Erickson

                                                1,7641320




                                                1,7641320













                                                • Note that the later answer of @eliastem is the same...

                                                  – Adam Erickson
                                                  Jul 4 '18 at 1:25



















                                                • Note that the later answer of @eliastem is the same...

                                                  – Adam Erickson
                                                  Jul 4 '18 at 1:25

















                                                Note that the later answer of @eliastem is the same...

                                                – Adam Erickson
                                                Jul 4 '18 at 1:25





                                                Note that the later answer of @eliastem is the same...

                                                – Adam Erickson
                                                Jul 4 '18 at 1:25











                                                2














                                                m_szFilePath.MakeLower();
                                                CFileFind finder;
                                                DWORD buffSize = MAX_PATH;
                                                char longPath[MAX_PATH];
                                                DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

                                                if( result == 0)
                                                {
                                                m_bExists = FALSE;
                                                return;
                                                }
                                                m_szFilePath = CString(longPath);
                                                m_szFilePath.Replace("/","\");
                                                m_szFilePath.Trim();
                                                //check if it does not ends in => remove it
                                                int length = m_szFilePath.GetLength();
                                                if( length > 0 && m_szFilePath[length - 1] == '\' )
                                                {
                                                m_szFilePath.Truncate( length - 1 );
                                                }
                                                BOOL bWorking = finder.FindFile(this->m_szFilePath);
                                                if(bWorking){
                                                bWorking = finder.FindNextFile();
                                                finder.GetCreationTime(this->m_CreationTime);
                                                m_szFilePath = finder.GetFilePath();
                                                m_szFileName = finder.GetFileName();

                                                this->m_szFileExtension = this->GetExtension( m_szFileName );

                                                m_szFileTitle = finder.GetFileTitle();
                                                m_szFileURL = finder.GetFileURL();
                                                finder.GetLastAccessTime(this->m_LastAccesTime);
                                                finder.GetLastWriteTime(this->m_LastWriteTime);
                                                m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
                                                m_szRootDirectory = finder.GetRoot();
                                                m_bIsArchive = finder.IsArchived();
                                                m_bIsCompressed = finder.IsCompressed();
                                                m_bIsDirectory = finder.IsDirectory();
                                                m_bIsHidden = finder.IsHidden();
                                                m_bIsNormal = finder.IsNormal();
                                                m_bIsReadOnly = finder.IsReadOnly();
                                                m_bIsSystem = finder.IsSystem();
                                                m_bIsTemporary = finder.IsTemporary();
                                                m_bExists = TRUE;
                                                finder.Close();
                                                }else{
                                                m_bExists = FALSE;
                                                }


                                                The variable m_szFileName contains the fileName.






                                                share|improve this answer



















                                                • 3





                                                  wow - that's a lot of code for "get file name" from path... :)

                                                  – Nim
                                                  Dec 15 '11 at 13:15






                                                • 4





                                                  @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

                                                  – James Kanze
                                                  Dec 15 '11 at 13:36











                                                • I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

                                                  – Lucian
                                                  Dec 15 '11 at 13:42
















                                                2














                                                m_szFilePath.MakeLower();
                                                CFileFind finder;
                                                DWORD buffSize = MAX_PATH;
                                                char longPath[MAX_PATH];
                                                DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

                                                if( result == 0)
                                                {
                                                m_bExists = FALSE;
                                                return;
                                                }
                                                m_szFilePath = CString(longPath);
                                                m_szFilePath.Replace("/","\");
                                                m_szFilePath.Trim();
                                                //check if it does not ends in => remove it
                                                int length = m_szFilePath.GetLength();
                                                if( length > 0 && m_szFilePath[length - 1] == '\' )
                                                {
                                                m_szFilePath.Truncate( length - 1 );
                                                }
                                                BOOL bWorking = finder.FindFile(this->m_szFilePath);
                                                if(bWorking){
                                                bWorking = finder.FindNextFile();
                                                finder.GetCreationTime(this->m_CreationTime);
                                                m_szFilePath = finder.GetFilePath();
                                                m_szFileName = finder.GetFileName();

                                                this->m_szFileExtension = this->GetExtension( m_szFileName );

                                                m_szFileTitle = finder.GetFileTitle();
                                                m_szFileURL = finder.GetFileURL();
                                                finder.GetLastAccessTime(this->m_LastAccesTime);
                                                finder.GetLastWriteTime(this->m_LastWriteTime);
                                                m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
                                                m_szRootDirectory = finder.GetRoot();
                                                m_bIsArchive = finder.IsArchived();
                                                m_bIsCompressed = finder.IsCompressed();
                                                m_bIsDirectory = finder.IsDirectory();
                                                m_bIsHidden = finder.IsHidden();
                                                m_bIsNormal = finder.IsNormal();
                                                m_bIsReadOnly = finder.IsReadOnly();
                                                m_bIsSystem = finder.IsSystem();
                                                m_bIsTemporary = finder.IsTemporary();
                                                m_bExists = TRUE;
                                                finder.Close();
                                                }else{
                                                m_bExists = FALSE;
                                                }


                                                The variable m_szFileName contains the fileName.






                                                share|improve this answer



















                                                • 3





                                                  wow - that's a lot of code for "get file name" from path... :)

                                                  – Nim
                                                  Dec 15 '11 at 13:15






                                                • 4





                                                  @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

                                                  – James Kanze
                                                  Dec 15 '11 at 13:36











                                                • I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

                                                  – Lucian
                                                  Dec 15 '11 at 13:42














                                                2












                                                2








                                                2







                                                m_szFilePath.MakeLower();
                                                CFileFind finder;
                                                DWORD buffSize = MAX_PATH;
                                                char longPath[MAX_PATH];
                                                DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

                                                if( result == 0)
                                                {
                                                m_bExists = FALSE;
                                                return;
                                                }
                                                m_szFilePath = CString(longPath);
                                                m_szFilePath.Replace("/","\");
                                                m_szFilePath.Trim();
                                                //check if it does not ends in => remove it
                                                int length = m_szFilePath.GetLength();
                                                if( length > 0 && m_szFilePath[length - 1] == '\' )
                                                {
                                                m_szFilePath.Truncate( length - 1 );
                                                }
                                                BOOL bWorking = finder.FindFile(this->m_szFilePath);
                                                if(bWorking){
                                                bWorking = finder.FindNextFile();
                                                finder.GetCreationTime(this->m_CreationTime);
                                                m_szFilePath = finder.GetFilePath();
                                                m_szFileName = finder.GetFileName();

                                                this->m_szFileExtension = this->GetExtension( m_szFileName );

                                                m_szFileTitle = finder.GetFileTitle();
                                                m_szFileURL = finder.GetFileURL();
                                                finder.GetLastAccessTime(this->m_LastAccesTime);
                                                finder.GetLastWriteTime(this->m_LastWriteTime);
                                                m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
                                                m_szRootDirectory = finder.GetRoot();
                                                m_bIsArchive = finder.IsArchived();
                                                m_bIsCompressed = finder.IsCompressed();
                                                m_bIsDirectory = finder.IsDirectory();
                                                m_bIsHidden = finder.IsHidden();
                                                m_bIsNormal = finder.IsNormal();
                                                m_bIsReadOnly = finder.IsReadOnly();
                                                m_bIsSystem = finder.IsSystem();
                                                m_bIsTemporary = finder.IsTemporary();
                                                m_bExists = TRUE;
                                                finder.Close();
                                                }else{
                                                m_bExists = FALSE;
                                                }


                                                The variable m_szFileName contains the fileName.






                                                share|improve this answer













                                                m_szFilePath.MakeLower();
                                                CFileFind finder;
                                                DWORD buffSize = MAX_PATH;
                                                char longPath[MAX_PATH];
                                                DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

                                                if( result == 0)
                                                {
                                                m_bExists = FALSE;
                                                return;
                                                }
                                                m_szFilePath = CString(longPath);
                                                m_szFilePath.Replace("/","\");
                                                m_szFilePath.Trim();
                                                //check if it does not ends in => remove it
                                                int length = m_szFilePath.GetLength();
                                                if( length > 0 && m_szFilePath[length - 1] == '\' )
                                                {
                                                m_szFilePath.Truncate( length - 1 );
                                                }
                                                BOOL bWorking = finder.FindFile(this->m_szFilePath);
                                                if(bWorking){
                                                bWorking = finder.FindNextFile();
                                                finder.GetCreationTime(this->m_CreationTime);
                                                m_szFilePath = finder.GetFilePath();
                                                m_szFileName = finder.GetFileName();

                                                this->m_szFileExtension = this->GetExtension( m_szFileName );

                                                m_szFileTitle = finder.GetFileTitle();
                                                m_szFileURL = finder.GetFileURL();
                                                finder.GetLastAccessTime(this->m_LastAccesTime);
                                                finder.GetLastWriteTime(this->m_LastWriteTime);
                                                m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
                                                m_szRootDirectory = finder.GetRoot();
                                                m_bIsArchive = finder.IsArchived();
                                                m_bIsCompressed = finder.IsCompressed();
                                                m_bIsDirectory = finder.IsDirectory();
                                                m_bIsHidden = finder.IsHidden();
                                                m_bIsNormal = finder.IsNormal();
                                                m_bIsReadOnly = finder.IsReadOnly();
                                                m_bIsSystem = finder.IsSystem();
                                                m_bIsTemporary = finder.IsTemporary();
                                                m_bExists = TRUE;
                                                finder.Close();
                                                }else{
                                                m_bExists = FALSE;
                                                }


                                                The variable m_szFileName contains the fileName.







                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Dec 15 '11 at 13:14









                                                LucianLucian

                                                2,5971418




                                                2,5971418








                                                • 3





                                                  wow - that's a lot of code for "get file name" from path... :)

                                                  – Nim
                                                  Dec 15 '11 at 13:15






                                                • 4





                                                  @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

                                                  – James Kanze
                                                  Dec 15 '11 at 13:36











                                                • I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

                                                  – Lucian
                                                  Dec 15 '11 at 13:42














                                                • 3





                                                  wow - that's a lot of code for "get file name" from path... :)

                                                  – Nim
                                                  Dec 15 '11 at 13:15






                                                • 4





                                                  @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

                                                  – James Kanze
                                                  Dec 15 '11 at 13:36











                                                • I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

                                                  – Lucian
                                                  Dec 15 '11 at 13:42








                                                3




                                                3





                                                wow - that's a lot of code for "get file name" from path... :)

                                                – Nim
                                                Dec 15 '11 at 13:15





                                                wow - that's a lot of code for "get file name" from path... :)

                                                – Nim
                                                Dec 15 '11 at 13:15




                                                4




                                                4





                                                @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

                                                – James Kanze
                                                Dec 15 '11 at 13:36





                                                @Nim My impression as well. In my own code, I use a one-liner: boost::filesystem::path( path ).filename().

                                                – James Kanze
                                                Dec 15 '11 at 13:36













                                                I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

                                                – Lucian
                                                Dec 15 '11 at 13:42





                                                I have a CFileInfo class that has that code. I just dumped the code here because it is tested and I did not want to risk anything... You could just use about 5 lines of code from this example.

                                                – Lucian
                                                Dec 15 '11 at 13:42











                                                2














                                                Dont use _splitpath() and _wsplitpath(). They are not safe, and they are obsolete!



                                                Instead, use their safe versions, namely _splitpath_s() and _wsplitpath_s()






                                                share|improve this answer




























                                                  2














                                                  Dont use _splitpath() and _wsplitpath(). They are not safe, and they are obsolete!



                                                  Instead, use their safe versions, namely _splitpath_s() and _wsplitpath_s()






                                                  share|improve this answer


























                                                    2












                                                    2








                                                    2







                                                    Dont use _splitpath() and _wsplitpath(). They are not safe, and they are obsolete!



                                                    Instead, use their safe versions, namely _splitpath_s() and _wsplitpath_s()






                                                    share|improve this answer













                                                    Dont use _splitpath() and _wsplitpath(). They are not safe, and they are obsolete!



                                                    Instead, use their safe versions, namely _splitpath_s() and _wsplitpath_s()







                                                    share|improve this answer












                                                    share|improve this answer



                                                    share|improve this answer










                                                    answered Aug 5 '13 at 11:57









                                                    hkBattousaihkBattousai

                                                    5,1591356104




                                                    5,1591356104























                                                        2














                                                        This should work too :



                                                        // strPath = "C:\Dir\File.bat" for example
                                                        std::string getFileName(const std::string& strPath)
                                                        {
                                                        size_t iLastSeparator = 0;
                                                        return strPath.substr((iLastSeparator = strPath.find_last_of("\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
                                                        }


                                                        If you can use it, Qt provide QString (with split, trim etc), QFile, QPath, QFileInfo etc to manipulate files, filenames and directories. And of course it's also cross plaftorm.






                                                        share|improve this answer





















                                                        • 4





                                                          For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

                                                          – Luc Touraille
                                                          Dec 15 '11 at 14:07











                                                        • edited. But the point was to make it short, as several working answers already have been given.

                                                          – typedef
                                                          Dec 15 '11 at 14:32






                                                        • 1





                                                          I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

                                                          – taktak004
                                                          Jan 22 '14 at 12:35











                                                        • @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

                                                          – phenmod
                                                          Dec 8 '15 at 10:08


















                                                        2














                                                        This should work too :



                                                        // strPath = "C:\Dir\File.bat" for example
                                                        std::string getFileName(const std::string& strPath)
                                                        {
                                                        size_t iLastSeparator = 0;
                                                        return strPath.substr((iLastSeparator = strPath.find_last_of("\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
                                                        }


                                                        If you can use it, Qt provide QString (with split, trim etc), QFile, QPath, QFileInfo etc to manipulate files, filenames and directories. And of course it's also cross plaftorm.






                                                        share|improve this answer





















                                                        • 4





                                                          For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

                                                          – Luc Touraille
                                                          Dec 15 '11 at 14:07











                                                        • edited. But the point was to make it short, as several working answers already have been given.

                                                          – typedef
                                                          Dec 15 '11 at 14:32






                                                        • 1





                                                          I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

                                                          – taktak004
                                                          Jan 22 '14 at 12:35











                                                        • @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

                                                          – phenmod
                                                          Dec 8 '15 at 10:08
















                                                        2












                                                        2








                                                        2







                                                        This should work too :



                                                        // strPath = "C:\Dir\File.bat" for example
                                                        std::string getFileName(const std::string& strPath)
                                                        {
                                                        size_t iLastSeparator = 0;
                                                        return strPath.substr((iLastSeparator = strPath.find_last_of("\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
                                                        }


                                                        If you can use it, Qt provide QString (with split, trim etc), QFile, QPath, QFileInfo etc to manipulate files, filenames and directories. And of course it's also cross plaftorm.






                                                        share|improve this answer















                                                        This should work too :



                                                        // strPath = "C:\Dir\File.bat" for example
                                                        std::string getFileName(const std::string& strPath)
                                                        {
                                                        size_t iLastSeparator = 0;
                                                        return strPath.substr((iLastSeparator = strPath.find_last_of("\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
                                                        }


                                                        If you can use it, Qt provide QString (with split, trim etc), QFile, QPath, QFileInfo etc to manipulate files, filenames and directories. And of course it's also cross plaftorm.







                                                        share|improve this answer














                                                        share|improve this answer



                                                        share|improve this answer








                                                        edited Oct 18 '13 at 0:20









                                                        Prashant Kumar

                                                        11.2k134059




                                                        11.2k134059










                                                        answered Dec 15 '11 at 13:38









                                                        typedeftypedef

                                                        919159




                                                        919159








                                                        • 4





                                                          For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

                                                          – Luc Touraille
                                                          Dec 15 '11 at 14:07











                                                        • edited. But the point was to make it short, as several working answers already have been given.

                                                          – typedef
                                                          Dec 15 '11 at 14:32






                                                        • 1





                                                          I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

                                                          – taktak004
                                                          Jan 22 '14 at 12:35











                                                        • @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

                                                          – phenmod
                                                          Dec 8 '15 at 10:08
















                                                        • 4





                                                          For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

                                                          – Luc Touraille
                                                          Dec 15 '11 at 14:07











                                                        • edited. But the point was to make it short, as several working answers already have been given.

                                                          – typedef
                                                          Dec 15 '11 at 14:32






                                                        • 1





                                                          I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

                                                          – taktak004
                                                          Jan 22 '14 at 12:35











                                                        • @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

                                                          – phenmod
                                                          Dec 8 '15 at 10:08










                                                        4




                                                        4





                                                        For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

                                                        – Luc Touraille
                                                        Dec 15 '11 at 14:07





                                                        For the sake of the future readers of your code, please use temporary variables with meaningful names instead of stuffing everything into a single line of code (and while you're at it, please encapsulate all this into a function getFilename or something like that).

                                                        – Luc Touraille
                                                        Dec 15 '11 at 14:07













                                                        edited. But the point was to make it short, as several working answers already have been given.

                                                        – typedef
                                                        Dec 15 '11 at 14:32





                                                        edited. But the point was to make it short, as several working answers already have been given.

                                                        – typedef
                                                        Dec 15 '11 at 14:32




                                                        1




                                                        1





                                                        I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

                                                        – taktak004
                                                        Jan 22 '14 at 12:35





                                                        I think it is WRONG. Should not you replace the last part: "strPath.size() - strPath.find_last_of(".")" by "strPath.find_last_of(".") - iLastSeparator"

                                                        – taktak004
                                                        Jan 22 '14 at 12:35













                                                        @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

                                                        – phenmod
                                                        Dec 8 '15 at 10:08







                                                        @taktak004 you are right, it should be ` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.find_last_of(".") - iLastSeparator );`

                                                        – phenmod
                                                        Dec 8 '15 at 10:08













                                                        0














                                                        For long time I was looking for a function able to properly decompose file path. For me this code is working perfectly for both Linux and Windows.



                                                        void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
                                                        {
                                                        #if defined _WIN32
                                                        const char *lastSeparator = strrchr(filePath, '\');
                                                        #else
                                                        const char *lastSeparator = strrchr(filePath, '/');
                                                        #endif

                                                        const char *lastDot = strrchr(filePath, '.');
                                                        const char *endOfPath = filePath + strlen(filePath);
                                                        const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
                                                        const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

                                                        if(fileDir)
                                                        _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

                                                        if(fileName)
                                                        _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

                                                        if(fileExt)
                                                        _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
                                                        }


                                                        Example results are:




                                                        fileDir: ''
                                                        fileName: ''
                                                        fileExt: ''

                                                        [.htaccess]
                                                        fileDir: ''
                                                        fileName: '.htaccess'
                                                        fileExt: ''

                                                        [a.exe]
                                                        fileDir: ''
                                                        fileName: 'a'
                                                        fileExt: '.exe'

                                                        [ab.c]
                                                        fileDir: 'a'
                                                        fileName: 'b'
                                                        fileExt: '.c'

                                                        [git-archive]
                                                        fileDir: ''
                                                        fileName: 'git-archive'
                                                        fileExt: ''

                                                        [git-archive.exe]
                                                        fileDir: ''
                                                        fileName: 'git-archive'
                                                        fileExt: '.exe'

                                                        [D:Gitmingw64libexecgit-core.htaccess]
                                                        fileDir: 'D:Gitmingw64libexecgit-core'
                                                        fileName: '.htaccess'
                                                        fileExt: ''

                                                        [D:Gitmingw64libexecgit-corea.exe]
                                                        fileDir: 'D:Gitmingw64libexecgit-core'
                                                        fileName: 'a'
                                                        fileExt: '.exe'

                                                        [D:Gitmingw64libexecgit-coregit-archive.exe]
                                                        fileDir: 'D:Gitmingw64libexecgit-core'
                                                        fileName: 'git-archive'
                                                        fileExt: '.exe'

                                                        [D:Gitmingw64libexecgit.coregit-archive.exe]
                                                        fileDir: 'D:Gitmingw64libexecgit.core'
                                                        fileName: 'git-archive'
                                                        fileExt: '.exe'

                                                        [D:Gitmingw64libexecgit-coregit-archiveexe]
                                                        fileDir: 'D:Gitmingw64libexecgit-core'
                                                        fileName: 'git-archiveexe'
                                                        fileExt: ''

                                                        [D:Gitmingw64libexecgit.coregit-archiveexe]
                                                        fileDir: 'D:Gitmingw64libexecgit.core'
                                                        fileName: 'git-archiveexe'
                                                        fileExt: ''


                                                        I hope this helps you also :)






                                                        share|improve this answer




























                                                          0














                                                          For long time I was looking for a function able to properly decompose file path. For me this code is working perfectly for both Linux and Windows.



                                                          void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
                                                          {
                                                          #if defined _WIN32
                                                          const char *lastSeparator = strrchr(filePath, '\');
                                                          #else
                                                          const char *lastSeparator = strrchr(filePath, '/');
                                                          #endif

                                                          const char *lastDot = strrchr(filePath, '.');
                                                          const char *endOfPath = filePath + strlen(filePath);
                                                          const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
                                                          const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

                                                          if(fileDir)
                                                          _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

                                                          if(fileName)
                                                          _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

                                                          if(fileExt)
                                                          _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
                                                          }


                                                          Example results are:




                                                          fileDir: ''
                                                          fileName: ''
                                                          fileExt: ''

                                                          [.htaccess]
                                                          fileDir: ''
                                                          fileName: '.htaccess'
                                                          fileExt: ''

                                                          [a.exe]
                                                          fileDir: ''
                                                          fileName: 'a'
                                                          fileExt: '.exe'

                                                          [ab.c]
                                                          fileDir: 'a'
                                                          fileName: 'b'
                                                          fileExt: '.c'

                                                          [git-archive]
                                                          fileDir: ''
                                                          fileName: 'git-archive'
                                                          fileExt: ''

                                                          [git-archive.exe]
                                                          fileDir: ''
                                                          fileName: 'git-archive'
                                                          fileExt: '.exe'

                                                          [D:Gitmingw64libexecgit-core.htaccess]
                                                          fileDir: 'D:Gitmingw64libexecgit-core'
                                                          fileName: '.htaccess'
                                                          fileExt: ''

                                                          [D:Gitmingw64libexecgit-corea.exe]
                                                          fileDir: 'D:Gitmingw64libexecgit-core'
                                                          fileName: 'a'
                                                          fileExt: '.exe'

                                                          [D:Gitmingw64libexecgit-coregit-archive.exe]
                                                          fileDir: 'D:Gitmingw64libexecgit-core'
                                                          fileName: 'git-archive'
                                                          fileExt: '.exe'

                                                          [D:Gitmingw64libexecgit.coregit-archive.exe]
                                                          fileDir: 'D:Gitmingw64libexecgit.core'
                                                          fileName: 'git-archive'
                                                          fileExt: '.exe'

                                                          [D:Gitmingw64libexecgit-coregit-archiveexe]
                                                          fileDir: 'D:Gitmingw64libexecgit-core'
                                                          fileName: 'git-archiveexe'
                                                          fileExt: ''

                                                          [D:Gitmingw64libexecgit.coregit-archiveexe]
                                                          fileDir: 'D:Gitmingw64libexecgit.core'
                                                          fileName: 'git-archiveexe'
                                                          fileExt: ''


                                                          I hope this helps you also :)






                                                          share|improve this answer


























                                                            0












                                                            0








                                                            0







                                                            For long time I was looking for a function able to properly decompose file path. For me this code is working perfectly for both Linux and Windows.



                                                            void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
                                                            {
                                                            #if defined _WIN32
                                                            const char *lastSeparator = strrchr(filePath, '\');
                                                            #else
                                                            const char *lastSeparator = strrchr(filePath, '/');
                                                            #endif

                                                            const char *lastDot = strrchr(filePath, '.');
                                                            const char *endOfPath = filePath + strlen(filePath);
                                                            const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
                                                            const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

                                                            if(fileDir)
                                                            _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

                                                            if(fileName)
                                                            _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

                                                            if(fileExt)
                                                            _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
                                                            }


                                                            Example results are:




                                                            fileDir: ''
                                                            fileName: ''
                                                            fileExt: ''

                                                            [.htaccess]
                                                            fileDir: ''
                                                            fileName: '.htaccess'
                                                            fileExt: ''

                                                            [a.exe]
                                                            fileDir: ''
                                                            fileName: 'a'
                                                            fileExt: '.exe'

                                                            [ab.c]
                                                            fileDir: 'a'
                                                            fileName: 'b'
                                                            fileExt: '.c'

                                                            [git-archive]
                                                            fileDir: ''
                                                            fileName: 'git-archive'
                                                            fileExt: ''

                                                            [git-archive.exe]
                                                            fileDir: ''
                                                            fileName: 'git-archive'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit-core.htaccess]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: '.htaccess'
                                                            fileExt: ''

                                                            [D:Gitmingw64libexecgit-corea.exe]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: 'a'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit-coregit-archive.exe]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: 'git-archive'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit.coregit-archive.exe]
                                                            fileDir: 'D:Gitmingw64libexecgit.core'
                                                            fileName: 'git-archive'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit-coregit-archiveexe]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: 'git-archiveexe'
                                                            fileExt: ''

                                                            [D:Gitmingw64libexecgit.coregit-archiveexe]
                                                            fileDir: 'D:Gitmingw64libexecgit.core'
                                                            fileName: 'git-archiveexe'
                                                            fileExt: ''


                                                            I hope this helps you also :)






                                                            share|improve this answer













                                                            For long time I was looking for a function able to properly decompose file path. For me this code is working perfectly for both Linux and Windows.



                                                            void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
                                                            {
                                                            #if defined _WIN32
                                                            const char *lastSeparator = strrchr(filePath, '\');
                                                            #else
                                                            const char *lastSeparator = strrchr(filePath, '/');
                                                            #endif

                                                            const char *lastDot = strrchr(filePath, '.');
                                                            const char *endOfPath = filePath + strlen(filePath);
                                                            const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
                                                            const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

                                                            if(fileDir)
                                                            _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

                                                            if(fileName)
                                                            _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

                                                            if(fileExt)
                                                            _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
                                                            }


                                                            Example results are:




                                                            fileDir: ''
                                                            fileName: ''
                                                            fileExt: ''

                                                            [.htaccess]
                                                            fileDir: ''
                                                            fileName: '.htaccess'
                                                            fileExt: ''

                                                            [a.exe]
                                                            fileDir: ''
                                                            fileName: 'a'
                                                            fileExt: '.exe'

                                                            [ab.c]
                                                            fileDir: 'a'
                                                            fileName: 'b'
                                                            fileExt: '.c'

                                                            [git-archive]
                                                            fileDir: ''
                                                            fileName: 'git-archive'
                                                            fileExt: ''

                                                            [git-archive.exe]
                                                            fileDir: ''
                                                            fileName: 'git-archive'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit-core.htaccess]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: '.htaccess'
                                                            fileExt: ''

                                                            [D:Gitmingw64libexecgit-corea.exe]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: 'a'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit-coregit-archive.exe]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: 'git-archive'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit.coregit-archive.exe]
                                                            fileDir: 'D:Gitmingw64libexecgit.core'
                                                            fileName: 'git-archive'
                                                            fileExt: '.exe'

                                                            [D:Gitmingw64libexecgit-coregit-archiveexe]
                                                            fileDir: 'D:Gitmingw64libexecgit-core'
                                                            fileName: 'git-archiveexe'
                                                            fileExt: ''

                                                            [D:Gitmingw64libexecgit.coregit-archiveexe]
                                                            fileDir: 'D:Gitmingw64libexecgit.core'
                                                            fileName: 'git-archiveexe'
                                                            fileExt: ''


                                                            I hope this helps you also :)







                                                            share|improve this answer












                                                            share|improve this answer



                                                            share|improve this answer










                                                            answered Feb 23 '17 at 19:46









                                                            no one specialno one special

                                                            458212




                                                            458212























                                                                0














                                                                shlwapi.lib/dll uses the HKCU registry hive internally.



                                                                It's best not to link to shlwapi.lib if you're creating a library or the product does not have a UI. If you're writing a lib then your code can be used in any project including those that don't have UIs.



                                                                If you're writing code that runs when a user is not logged in (e.g. service [or other] set to start at boot or startup) then there's no HKCU. Lastly, shlwapi are settlement functions; and as a result high on the list to deprecate in later versions of Windows.






                                                                share|improve this answer






























                                                                  0














                                                                  shlwapi.lib/dll uses the HKCU registry hive internally.



                                                                  It's best not to link to shlwapi.lib if you're creating a library or the product does not have a UI. If you're writing a lib then your code can be used in any project including those that don't have UIs.



                                                                  If you're writing code that runs when a user is not logged in (e.g. service [or other] set to start at boot or startup) then there's no HKCU. Lastly, shlwapi are settlement functions; and as a result high on the list to deprecate in later versions of Windows.






                                                                  share|improve this answer




























                                                                    0












                                                                    0








                                                                    0







                                                                    shlwapi.lib/dll uses the HKCU registry hive internally.



                                                                    It's best not to link to shlwapi.lib if you're creating a library or the product does not have a UI. If you're writing a lib then your code can be used in any project including those that don't have UIs.



                                                                    If you're writing code that runs when a user is not logged in (e.g. service [or other] set to start at boot or startup) then there's no HKCU. Lastly, shlwapi are settlement functions; and as a result high on the list to deprecate in later versions of Windows.






                                                                    share|improve this answer















                                                                    shlwapi.lib/dll uses the HKCU registry hive internally.



                                                                    It's best not to link to shlwapi.lib if you're creating a library or the product does not have a UI. If you're writing a lib then your code can be used in any project including those that don't have UIs.



                                                                    If you're writing code that runs when a user is not logged in (e.g. service [or other] set to start at boot or startup) then there's no HKCU. Lastly, shlwapi are settlement functions; and as a result high on the list to deprecate in later versions of Windows.







                                                                    share|improve this answer














                                                                    share|improve this answer



                                                                    share|improve this answer








                                                                    edited Dec 28 '18 at 16:00









                                                                    rguerin

                                                                    50817




                                                                    50817










                                                                    answered Dec 28 '18 at 12:38









                                                                    BrookBrook

                                                                    1




                                                                    1






























                                                                        draft saved

                                                                        draft discarded




















































                                                                        Thanks for contributing an answer to Stack Overflow!


                                                                        • Please be sure to answer the question. Provide details and share your research!

                                                                        But avoid



                                                                        • Asking for help, clarification, or responding to other answers.

                                                                        • Making statements based on opinion; back them up with references or personal experience.


                                                                        To learn more, see our tips on writing great answers.




                                                                        draft saved


                                                                        draft discarded














                                                                        StackExchange.ready(
                                                                        function () {
                                                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8520560%2fget-a-file-name-from-a-path%23new-answer', 'question_page');
                                                                        }
                                                                        );

                                                                        Post as a guest















                                                                        Required, but never shown





















































                                                                        Required, but never shown














                                                                        Required, but never shown












                                                                        Required, but never shown







                                                                        Required, but never shown

































                                                                        Required, but never shown














                                                                        Required, but never shown












                                                                        Required, but never shown







                                                                        Required, but never shown







                                                                        Popular posts from this blog

                                                                        Monofisismo

                                                                        Angular Downloading a file using contenturl with Basic Authentication

                                                                        Olmecas