Awesome Open Source
Awesome Open Source

Unix-style pathname pattern expansion

Table of Contents

Quick Start

  • This library is available in two flavors:
    1. Two file version: glob.h and glob.cpp
    2. Single header file version in single_include/
  • No external dependencies - just the standard library
  • Requires C++17 std::filesystem
  • MIT License

Build Library and Standalone Sample

cmake -Hall -Bbuild
cmake --build build

# run standalone `glob` sample
./build/standalone/glob --help


// Match on a single pattern
for (auto& p : glob::glob("~/.b*")) {                // e.g., .bash_history, .bashrc
  // do something with `p`

// Match on multiple patterns
for (auto& p : glob::glob({"*.png", "*.jpg"})) {     // e.g., foo.png, bar.jpg
  // do something with `p`

// Match recursively with `rglob`
for (auto& p : glob::rglob("**/*.hpp")) {            // e.g., include/foo.hpp, include/foo/bar.hpp
  // do something with `p`


/// e.g., glob("*.hpp")
/// e.g., glob("**/*.cpp")
/// e.g., glob("test_files_02/[0-9].txt")
/// e.g., glob("/usr/local/include/nc*.h")
/// e.g., glob("test_files_02/?.txt")
vector<filesystem::path> glob(string pathname);

/// Globs recursively
/// e.g., rglob("Documents/Projects/Foo/**/*.hpp")
/// e.g., rglob("test_files_02/*[0-9].txt")
vector<filesystem::path> rglob(string pathname);

There are also two convenience functions to glob on a list of patterns:

/// e.g., glob({"*.png", "*.jpg"})
vector<filesystem::path> glob(vector<string> pathnames);

/// Globs recursively
/// e.g., rglob({"**/*.h", "**/*.hpp", "**/*.cpp"})
vector<filesystem::path> rglob(vector<string> pathnames);


Wildcard Matches Example
* any characters *.txt matches all files with the txt extension
? any one character ??? matches files with 3 characters long
[] any character listed in the brackets [ABC]* matches files starting with A,B or C
[-] any character in the range listed in brackets [A-Z]* matches files starting with capital letters
[!] any character listed in the brackets [!ABC]* matches files that do not start with A,B or C


The following examples use the standalone sample that is part of this repository to illustrate the library functionality.

[email protected]:~$ ./build/standalone/glob -h
Run glob to find all the pathnames matching a specified pattern
  ./build/standalone/glob [OPTION...]

  -h, --help       Show help
  -v, --version    Print the current version number
  -r, --recursive  Run glob recursively
  -i, --input arg  Patterns to match

Match file extensions

[email protected]:~$ tree
├── include
│   └── foo
│       ├── bar.hpp
│       ├── baz.hpp
│       └── foo.hpp
└── test
    ├── bar.cpp
    ├── doctest.hpp
    ├── foo.cpp
    └── main.cpp

3 directories, 7 files

[email protected]:~$ ./glob -i "**/*.hpp"

[email protected]:~$ ./glob -i "**/**/*.hpp"

NOTE If you run glob recursively, i.e., using rglob:

[email protected]:~$ ./glob -r -i "**/*.hpp"

Match files in absolute pathnames

[email protected]:~$ ./glob -i '/usr/local/include/nc*.h'

Wildcards: Match a range of characters listed in brackets ('[]')

[email protected]:~$ ls test_files_02
1.txt 2.txt 3.txt 4.txt

[email protected]:~$ ./glob -i 'test_files_02/[0-9].txt'

[email protected]:~$ ./glob -i 'test_files_02/[1-2]*'
[email protected]:~$ ls test_files_03
file1.txt file2.txt file3.txt file4.txt

[email protected]:~$ ./glob -i 'test_files_03/file[0-9].*'

Exclude files from the matching

[email protected]:~$ ls test_files_01

[email protected]:~$ ./glob -i 'test_files_01/*[!__init__].py'

[email protected]:~$ ./glob -i 'test_files_01/*[!__init__][!bar].py'

[email protected]:~$ ./glob -i 'test_files_01/[!_]*.py'

Wildcards: Match any one character with question mark ('?')

[email protected]:~$ ls test_files_02
1.txt 2.txt 3.txt 4.txt

[email protected]:~$ ./glob -i 'test_files_02/?.txt'
[email protected]:~$ ls test_files_03
file1.txt file2.txt file3.txt file4.txt

[email protected]:~$ ./glob -i 'test_files_03/????[3-4].txt'

Case sensitivity

glob matching is case-sensitive:

[email protected]:~$ ls test_files_05
file1.png file2.png file3.PNG file4.PNG

[email protected]:~$ ./glob -i 'test_files_05/*.png'

[email protected]:~$ ./glob -i 'test_files_05/*.PNG'

[email protected]:~$ ./glob -i "test_files_05/*.png","test_files_05/*.PNG"

Tilde expansion

[email protected]:~$ ./glob -i "~/.b*"

[email protected]:~$ ./glob -i "~/Documents/Projects/glob/**/glob/*.h"


Contributions are welcome, have a look at the document for more information.


The project is available under the MIT license.

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
c-plus-plus (18,960
cpp11 (253
unix (223
cpp17 (223
filesystem (215
lightweight (200
header-only (159
cpp14 (148
pattern-matching (51
single-header-lib (39
glob (30
pattern-recognition (25
single-header (25