More Globbling with the fnmatch() Function

Globbing is the use of wildcards to match filenames, which is something I touched upon a few Lessons ago. It lead me to the glob() function, which reads a pathname for matching files. Often mentioned along with the glob() function, is the fnmatch() function, which serves a similar purpose.

As you might guess, the FN in fnmatch() stands for filename. It’s more of a text-searching function than a true file function; unlike glob(), the fnmatch() function doesn’t scour a pathname on a file system for existing files. Instead, it uses a glob pattern to search a string. Here is the man page format:

int fnmatch(const char *pattern, const char *string, int flags);

The pattern is a string that can contain shell wildcards, such as *.c.

The string is the text to search.

The flags argument includes a series of defined constants, logically OR’d, to control the function’s behavior. For example, you can search for backslashes as characters instead of escape sequences. The value zero is specified for no flags.

The return value is zero if the pattern matches. Otherwise a non-zero value is returned upon error. The return value can also be compared with the FNM_NOMATCH defined constant to confirm that no match was found instead of a true error condition.

Use of the fnmatch() function requires including the fnmatch.h header file.

The following code demonstrates the fnmatch() function:

2021_06_19-Lesson.c

#include <stdio.h>
#include <fnmatch.h>

int main()
{
    char pattern[] = "*.c";
    char string[] = "hello.c";
    int r;

    r = fnmatch(pattern,string,0);
    if( r==0 )
        printf("'%s' matches '%s'\n",
                pattern,
                string
              );
    else if( r==FNM_NOMATCH )
        printf("'%s' does not match '%s'\n",
                pattern,
                string
              );
    else
        fprintf(stderr,"fnmatch() error\n");

    return(0);
}

The fnmatch.h header file is included at Line 2. The fnmatch() function is used at Line 10, with variables pattern and string, which are declared at Lines 6 and 7. No flags are set (zero is specified as the third argument). The return value is saved in int variable r.

At Line 11, the return value is compared with zero, meaning a match was found. A printf() statement outputs the cheerful results.

The else if statement at Line 16 checks for the FNM_NOMATCH defined constant in the return value. If so, the function didn’t error but no match was found. A sober message is output at Line 17 (split across Lines 17 through 20).

The final else statement at Line 21 outputs an error condition.

Here’s a sample run:

'*.c' matches 'hello.c'

If you modify Line 7 to read char string[] = "hello.txt";, then build and run, the output becomes:

'*.c' does not match 'hello.txt'

As I wrote earlier, no files are opened or scanned from any directory with this function; fnmatch() is purely a text-matching function, though the first argument uses shell wildcards (globbing) for matching purposes.

I suppose you could use the fnmatch() function as a text-searching tool, such as if you wanted to search a string by using the * and ? wildcards. This approach opens the door to coding regular expressions, which is a can of worms I may open in a future series of Lessons.

Leave a Reply