Easy way to remove extension from a filename?
I am trying to grab the raw filename without the extension from the filename passed in arguments:
int main ( int argc, char *argv[] )
{
// Check to make sure there is a single argument
i开发者_JAVA技巧f ( argc != 2 )
{
cout<<"usage: "<< argv[0] <<" <filename>\n";
return 1;
}
// Remove the extension if it was supplied from argv[1] -- pseudocode
char* filename = removeExtension(argv[1]);
cout << filename;
}
The filename should for example be "test" when I passed in "test.dat".
size_t lastindex = fullname.find_last_of(".");
string rawname = fullname.substr(0, lastindex);
Beware of the case when there is no "." and it returns npos
This works:
std::string remove_extension(const std::string& filename) {
size_t lastdot = filename.find_last_of(".");
if (lastdot == std::string::npos) return filename;
return filename.substr(0, lastdot);
}
Since C++17 you can use std::filesystem::path::replace_extension with a parameter to replace the extension or without to remove it:
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path p = "/foo/bar.txt";
std::cout << "Was: " << p << std::endl;
std::cout << "Now: " << p.replace_extension() << std::endl;
}
Compile it with:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Running the resulting binary leaves you with:
Was: "/foo/bar.txt"
Now: "/foo/bar"
However this does only remove the last file extension:
Was: "/foo/bar.tar.gz"
Now: "/foo/bar.tar"
In my opinion it is easiest, and the most readable solution:
#include <boost/filesystem/convenience.hpp>
std::string removeFileExtension(const std::string& fileName)
{
return boost::filesystem::change_extension(fileName, "").string();
}
For those who like boost:
Use boost::filesystem::path::stem. It returns the filename without the last extension. So ./myFiles/foo.bar.foobar becomes foo.bar. So when you know you are dealing with only one extension you could do the follwing:
boost::filesystem::path path("./myFiles/fileWithOneExt.myExt");
std::string fileNameWithoutExtension = path.stem().string();
When you have to deal with multiple extensions you might do the following:
boost::filesystem::path path("./myFiles/fileWithMultiExt.myExt.my2ndExt.my3rdExt");
while(!path.extension().empty())
{
path = path.stem();
}
std::string fileNameWithoutExtensions = path.stem().string();
(taken from here: http://www.boost.org/doc/libs/1_53_0/libs/filesystem/doc/reference.html#path-decomposition found in the stem section)
BTW works with rooted paths, too.
The following works for a std::string:
string s = filename;
s.erase(s.find_last_of("."), string::npos);
More complex, but with respect to special cases (for example: "foo.bar/baz", "c:foo.bar", works for Windows too)
std::string remove_extension(const std::string& path) {
if (path == "." || path == "..")
return path;
size_t pos = path.find_last_of("\\/.");
if (pos != std::string::npos && path[pos] == '.')
return path.substr(0, pos);
return path;
}
You can do this easily :
string fileName = argv[1];
string fileNameWithoutExtension = fileName.substr(0, fileName.rfind("."));
Note that this only work if there is a dot. You should test before if there is a dot, but you get the idea.
In case someone just wants a simple solution for windows:
Use PathCchRemoveExtension
->MSDN
... or PathRemoveExtension
(deprecated!) ->MSDN
Try the following trick to extract the file name from path with no extension in c++ with no external libraries in c++ :
#include <iostream>
#include <string>
using std::string;
string getFileName(const string& s) {
char sep = '/';
#ifdef _WIN32
sep = '\\';
#endif
size_t i = s.rfind(sep, s.length());
if (i != string::npos)
{
string filename = s.substr(i+1, s.length() - i);
size_t lastindex = filename.find_last_of(".");
string rawname = filename.substr(0, lastindex);
return(rawname);
}
return("");
}
int main(int argc, char** argv) {
string path = "/home/aymen/hello_world.cpp";
string ss = getFileName(path);
std::cout << "The file name is \"" << ss << "\"\n";
}
Just loop through the list and replace the first (or last) occurrence of a '.' with a NULL terminator. That will end the string at that point.
Or make a copy of the string up until the '.', but only if you want to return a new copy. Which could get messy since a dynamically allocated string could be a source of memory leak.
for(len=strlen(extension);len>= 0 && extension[len] != '.';len--)
;
char * str = malloc(len+1);
for(i=0;i<len;i++)
str[i] = extension[i];
str[i] = '\0'l
精彩评论