41

How do you get a file extension (like .tiff) from a filename in C?

Thanks!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
errorhandler
  • 1,757
  • 3
  • 22
  • 29
  • Possible duplicate of [Getting file extension in C language](http://stackoverflow.com/questions/3035225/getting-file-extension-in-c-language) – nibot Mar 04 '17 at 18:15

4 Answers4

78
const char *get_filename_ext(const char *filename) {
    const char *dot = strrchr(filename, '.');
    if(!dot || dot == filename) return "";
    return dot + 1;
}

printf("%s\n", get_filename_ext("test.tiff"));
printf("%s\n", get_filename_ext("test.blah.tiff"));
printf("%s\n", get_filename_ext("test."));
printf("%s\n", get_filename_ext("test"));
printf("%s\n", get_filename_ext("..."));
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • After `dot = strrchr(filename, '.');`, `dot != NULL` implies that `*dot == '.'` so your test ought to be simply `if(dot)`. – Chris Lutz Mar 15 '11 at 09:07
  • I'm getting an error: `renamer.c:11: warning: incompatible implicit declaration of built-in function ‘strrchr’` – errorhandler Mar 15 '11 at 09:08
  • 12
    For most practical purposes, if the last dot is the first character of the basename, then it should not be treated as a file extenstion. For example in `~/.forward`, ".forward" isn't an extension. – Steve Jessop Mar 15 '11 at 10:00
  • That doesn't really matter... because I'm just using it batch rename my photos. – errorhandler Mar 16 '11 at 04:30
  • Once you have extracted the file extension a useful addendum might be the [`strcmp()`](http://www.cplusplus.com/reference/cstring/strcmp/) routine from `string.h`. It will allow you to compare the file extension with a given string and perform a certain action, e.g. `if (strcmp(ext,"tiff") == 0) ...` – mabalenk Sep 11 '19 at 08:18
25

Find the last dot with strrchr, then advance 1 char

#include <stdio.h> /* printf */
#include <string.h> /* strrchr */

ext = strrchr(filename, '.');
if (!ext) {
    /* no extension */
} else {
    printf("extension is %s\n", ext + 1);
}
pmg
  • 106,608
  • 13
  • 126
  • 198
  • There's no need to copy it - you'll return a part of the string which ends with the end of the original string, so no modifications are necessary. – ThiefMaster Mar 15 '11 at 09:11
7

You can use the strrchr function, which searches for the last occurrence of a character in a string, to find the final dot. From there, you can read off the rest of the string as the extension.

pat
  • 12,587
  • 1
  • 23
  • 52
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
4

Here is a version which works also for file (or directory) paths:

#include <assert.h>
#include <string.h>

const char *FileSuffix(const char path[])
{
    const char *result;
    int i, n;

    assert(path != NULL);
    n = strlen(path);
    i = n - 1;
    while ((i > 0) && (path[i] != '.') && (path[i] != '/') && (path[i] != '\\')) {
        i--;
    }
    if ((i > 0) && (i < n - 1) && (path[i] == '.') && (path[i - 1] != '/') && (path[i - 1] != '\\')) {
        result = path + i;
    } else {
        result = path + n;
    }
    return result;
}


int main(void)
{
    assert(strcmp(FileSuffix(""), "") == 0);
    assert(strcmp(FileSuffix("."), "") == 0);
    assert(strcmp(FileSuffix("f"), "") == 0);
    assert(strcmp(FileSuffix("foo"), "") == 0);     
    assert(strcmp(FileSuffix("foo."), "") == 0);    
    assert(strcmp(FileSuffix(".foo"), "") == 0);
    assert(strcmp(FileSuffix("foo.bar"), ".bar") == 0); 
    assert(strcmp(FileSuffix("foo/.bar"), "") == 0);
    assert(strcmp(FileSuffix("foo\\.bar"), "") == 0);   
    assert(strcmp(FileSuffix("foo/bar.baz.qux"), ".qux") == 0);
    assert(strcmp(FileSuffix("foo\\bar.baz.qux"), ".qux") == 0);
    assert(strcmp(FileSuffix("foo.bar.baz/qux"), "") == 0);
    assert(strcmp(FileSuffix("foo.bar.baz\\qux"), "") == 0);    
    return 0;
}
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60