View on GitHub

Computer Architecture and Operating Systems

Course taught at Faculty of Computer Science of Higher School of Economics

Patterns

Pattern matching

Shell patterns

Patterns are used in Linux Shell to filter files by their names. They are used for filename generation before executing a Shell command. Performed by Shell, not by command being called (i.e. not by ls in the example below).

Details on Shell patterns can be found in this and that documents.

This example demonstrates using Shell patters by the ls utility:

$ ls
a  a0  aa  aaa  aaaa  abab  abba  acb  b  b0  bb  bbb  cabba  cba
$ ls a*
a  a0  aa  aaa  aaaa  abab  abba  acb
$ ls a?b
acb
$ ls c*a
cabba  cba
$ ls [ab]*
a  a0  aa  aaa  aaaa  abab  abba  acb  b  b0  bb  bbb
$ ls *[a-z]
a  aa  aaa  aaaa  abab  abba  acb  b  bb  bbb  cabba  cba
$ ls *[^a-z]
a0  b0

The same can be done with other Linux utilities such as: cp, mv, rm, cat, etc. For these tools, Shell will provide file names in exactly the same way.

Patterns in Linux utilities

Pattern matching is also used in some Linux utilities. For example, the find utility uses pattern to search for files in a directory hierarchy.

For example, the command below searches for PDF-files with the OS_ prefix in a directory tree:

$ find . -name "OS_*.pdf"
./part2os/01_OS_Architecture/OS_Lecture_01.pdf
./part2os/02_C/OS_Lecture_02.pdf
./part2os/03_SystemCalls/OS_Lecture_03.pdf
./part2os/04_Linking/OS_Lecture_04.pdf
./part2os/05_Strings/OS_Lecture_05.pdf
./part2os/06_Processes/OS_Lecture_06.pdf

Patterns in C

Program in C sometimes need to whether a file name or path matches a specific pattern. This can be done using the fnmatch function. The function returns zero if the name matches the specified pattern. The patterns are the same patterns as in Shell. Please pay attention for the flags argument of the function.

The example below matches pattern in argv[1] and name in argv[2]:

Command:

tatarnikov@akos:~$ ./match "/h*/*ov" "/home/tatarnikov"
'/home/tatarnikov' matches '/h*/*ov'

Code:

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

int main(int argc, char *argv[]) {
    const char* pattern = argv[1];
    const char* name = argv[2];
    if (fnmatch(pattern, name, FNM_PATHNAME) == 0) {
        printf("'%s' matches '%s'\n", name, pattern);
    } else {
        printf("'%s' mismatches '%s'\n", name, pattern);
    }
    return 0;
}

Limitations of patterns

Patterns are good at filtering string that can be described by a simple template (e.g. file name). However, they are not suitable for more complex tasks. For such tasks, a more powerful tool required - regular expressions.