What is the simplest way to get the file name that from a path?
string filename = \"C:\\\\MyDirectory\\\\MyFile.bat\"
In this example, I s
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.
_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;
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.
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...
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.
Dont use _splitpath()
and _wsplitpath()
. They are not safe, and they are obsolete!
Instead, use their safe versions, namely _splitpath_s() and _wsplitpath_s()