Say there is a file called 12345.jpg. In C, how can I get the file extension so that I can compare with some file extension? If there are any inbuilt functions, kindly please let me know.
- SO 290488 covers a lot of the same ground.Jonathan Leffler– Jonathan Leffler2010-06-14 06:13:49 +00:00Commented Jun 14, 2010 at 6:13
- So is this - stackoverflow.com/questions/51949/…Ofek Shilon– Ofek Shilon2010-06-14 06:46:26 +00:00Commented Jun 14, 2010 at 6:46
- Possible duplicate of Getting file extension in Cnibot– nibot2017-03-04 18:15:48 +00:00Commented Mar 4, 2017 at 18:15
- SO 51949, mentioned by Ofek Shilon, is a C++ question. The answers are not appropriate for C. SO 5309471, mentioned by nibot, was asked a year or so after this. There's a cross-reference back to this question, though. SO 290488, mentioned by YT, is tagged with both C++ and C, though the code it shows is pure C (that would also compile in C++, I think, based on eyeballing, not on testing it).Jonathan Leffler– Jonathan Leffler2022-11-28 22:50:38 +00:00Commented Nov 28, 2022 at 22:50
Add a comment |
4 Answers
A function to do that, along with a test harness:
#include <stdio.h> #include <string.h> const char *getExt (const char *fspec) { char *e = strrchr (fspec, '.'); if (e == NULL) e = ""; // fast method, could also use &(fspec[strlen(fspec)]). return e; } int main (int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) { printf ("[%s] - > [%s]\n", argv[i], getExt (argv[i])); } return 0; } Running this with:
./program abc abc. abc.1 .xyz abc.def abc.def.ghi gives you:
[abc] - > [] [abc.] - > [.] [abc.1] - > [.1] [.xyz] - > [.xyz] [abc.def] - > [.def] [abc.def.ghi] - > [.ghi] 2 Comments
tomlogic
+1 for
strrchr. Best method for finding the last instance of a character in a string.Michael Closson
Just in case anyone misses it.
getExt() assumes that fspec is a basename, not full path. Consider for e.g., my.dir/file. Use basename() to get the basename from a full path.Probably:
#include <string.h> char *extn = strrchr(filename, '.'); That will give you a pointer to the period of the extension, or a null pointer if there is no extension. You might need to do some more due diligence to ensure that there isn't a slash after the dot, amongst other things.
4 Comments
drawnonward
strrchr(filename+1,'.'); would handle names like .svn that start with a dot but have no extension.Jonathan Leffler
@drawnonward - indubitably, if you consider that to be a file name with no extension, rather than as an extension with no name. That is another of the 'due diligence' cases to be considered. However, if the OP is looking to compare the found extension with a fairly short list of known extensions, then the fact that
.svn is not in the list means it probably won't matter anyway.Jonathan Leffler
@drawnonward: I misread what you were saying - you make a valid point. However, that wouldn't help with absolute pathnames which start with a '/', or relative names containing a slash (
subdir/.svn). There's a case for saying you need to find the start of the basename of the file (after the last slash, but you have to worry about trailing slashes and root) and then look for a dot not in the first position. I guess that means the parent directory '..' has the name 'dot' followed by an extension starting with a dot and nothing more...There's usually another curve ball to deal with.syockit
@drawnonward Might cause segmentation fault if filename is empty string.
There's a portable CRT solution: _splitpath.
In windows there's also an undocumented shell32 API called PathGetExtension, but that's evil in so many ways that I probably shouldn't have noted that.
5 Comments
paxdiablo
This is obviously some new definition of the word "portable" of which I was previously unaware :-) With apologies to Douglas Adams of HHGTTG fame.
mtvec
Indeed, never seen the word "portable" and a link to msdn in the same sentence:-)
Ofek Shilon
My bad, my bad! Won't edit the answer, for others to enjoy :)
paxdiablo
Well, yeah, the answer is still useful so I wouldn't edit it. If you're on an MS platform, it's probably preferable to use
_splitpath than write your own (such as in my answer).Ofek Shilon
Of course - I considered removing 'portable' (where was my head, really?) but dropped it.