DotNet.Glob 2.0.2

A fast globbing library for .NET applications, including .net core. Doesn't use Regex.

There is a newer version of this package available.
See the version list below for details.
Install-Package DotNet.Glob -Version 2.0.2
dotnet add package DotNet.Glob --version 2.0.2
<PackageReference Include="DotNet.Glob" Version="2.0.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DotNet.Glob --version 2.0.2
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

DotNet.Glob

A fast (probably the fastest) globbing library for .NET.

| Branch | Build Status | NuGet |
| ------------- | ------------- | ----- |
| Master |Build master | NuGet |
| Develop | Build status | NuGet |

This library does not use Regex - I wanted to make something much faster.
The latest benchmarks show that DotNet.Glob signficantly outperforms Regex.
The benchmarks use BenchmarkDotNet and can be located inside this repo. Just dotnet run them. Some Benchmark results have also been published on the wiki: https://github.com/dazinator/DotNet.Glob/wiki/Benchmarks-(vs-Compiled-Regex)

Usage

  1. Install the NuGet package. Install-Package DotNet.Glob
  2. Add using statement:
    using DotNet.Globbing;
  3. Parse a glob from a pattern
 var glob = Glob.Parse("p?th/*a[bcd]b[e-g]a[1-4][!wxyz][!a-c][!1-3].*");
 var isMatch = glob.IsMatch("pAth/fooooacbfa2vd4.txt");

Build a glob fluently

You can also use the GlobBuilder class if you wish to build up a glob using a fluent syntax.
This is also more efficient as it avoids having to parse the glob from a string pattern.

So to build the following glob pattern: /foo?\\*[abc][!1-3].txt:


  var glob = new GlobBuilder()
                .PathSeperator()
                .Literal("foo")
                .AnyCharacter()
                .PathSeperator(PathSeperatorKind.BackwardSlash)
                .Wildcard()
                .OneOf('a', 'b', 'c')
                .NumberNotInRange('1', '3')
                .Literal(".txt")
                .ToGlob();

   var isMatch = glob.IsMatch(@"/fooa\\barrra4.txt"); // returns true.

Patterns

The following patterns are supported (from wikipedia):

| Wildcard | Description | Example | Matches | Does not match |
| -------- | ----------- | ------- | ------- | -------------- |
| * | matches any number of any characters including none | Law*| Law, Laws, or Lawyer |
| ? | matches any single character | ?at | Cat, cat, Bat or bat | at |
| [abc] | matches one character given in the bracket | [CB]at | Cat or Bat | cat or bat |
| [a-z] | matches one character from the range given in the bracket | Letter[0-9] | Letter0, Letter1, Letter2 up to Letter9 | Letters, Letter or Letter10 |
| [!abc] | matches one character that is not given in the bracket | [!C]at | Bat, bat, or cat | Cat |
| [!a-z] | matches one character that is not from the range given in the bracket | Letter[!3-5] | Letter1, Letter2, Letter6 up to Letter9 and Letterx etc. | Letter3, Letter4, Letter5 or Letterxx |

In addition, DotNet Glob also supports:

| Wildcard | Description | Example | Matches | Does not match |
| -------- | ----------- | ------- | ------- | -------------- |
| ** | matches any number of path / directory segments. When used must be the only contents of a segment. | /**/some.* | /foo/bar/bah/some.txt, /some.txt, or /foo/some.txt |

Advanced Usages

Parsing options.

By default, when your glob pattern is parsed, DotNet.Glob will only allow literals which are valid for path / directory names.
These are:

  1. Any Letter (A-Z, a-z) or Digit
  2. ., , !, #, -, ;, =, @, ~, _, :

This is optimised for matching against paths / directory strings.
However, introduced in version 1.6.4, you can override this behaviour so that you can include arbitrary characters in your literals. For example, here is a pattern that matches the literal &quot;Stuff:

    // Overide the default options globally for all matche:
    GlobParseOptions.Default.Parsing.AllowInvalidPathCharacters = true;
    DotNet.Globbing.Glob.Parse("\"Stuff*").IsMatch("\"Stuff"); // true;    

You can also just set these options on a per glob pattern basis:

    GlobOptions options = new GlobOptions();
    options.Parsing.AllowInvalidPathCharacters = allowInvalidPathCharcters;
    DotNet.Globbing.Glob.Parse("\"Stuff*", globParseOptions).IsMatch("\"Stuff"); // true; 

Case Sensitivity (Available as of version >= 2.0.0)

By default, evaluation is case-sensitive unless you specify otherwise.

    GlobOptions options = new GlobOptions();
    options.Evaluation.CaseInsensitive = true;
    DotNet.Globbing.Glob.Parse("foo*", globParseOptions).IsMatch("FOo"); // true; 

Setting CaseInsensitive has an impact on:

  • Letter Ranges. Any letter range (i.e '[A-Z]') will now match both lower or upper case characters.
  • Character Lists. Any character list (i.e '[ABC]') will now match both lower or upper case characters.
  • Literals. Any literal (i.e 'foo') will now match both lower or upper case characters i.e FoO will match foO etc.

Match Generation

Given a glob, you can generate random matches, or non matches, for that glob.
For example, given the glob pattern /f?o/bar/**/*.txt you could generate matching strings like /foo/bar/ajawd/awdaw/adw-ad.txt or random non matching strings.

  var dotnetGlob = Glob.Parse(pattern);
  var generator = new GlobMatchStringGenerator(dotnetGlob.Tokens);

  for (int i = 0; i < 10; i++)
  {
          var testString = generator.GenerateRandomMatch();
          var result = dotnetGlob.IsMatch(testString);
          // result is always true.

          // generate a non match.
          testString = generator.GenerateRandomNonMatch();
          var result = dotnetGlob.IsMatch(testString);
           // result is always false.
  }

DotNet.Glob

A fast (probably the fastest) globbing library for .NET.

| Branch | Build Status | NuGet |
| ------------- | ------------- | ----- |
| Master |Build master | NuGet |
| Develop | Build status | NuGet |

This library does not use Regex - I wanted to make something much faster.
The latest benchmarks show that DotNet.Glob signficantly outperforms Regex.
The benchmarks use BenchmarkDotNet and can be located inside this repo. Just dotnet run them. Some Benchmark results have also been published on the wiki: https://github.com/dazinator/DotNet.Glob/wiki/Benchmarks-(vs-Compiled-Regex)

Usage

  1. Install the NuGet package. Install-Package DotNet.Glob
  2. Add using statement:
    using DotNet.Globbing;
  3. Parse a glob from a pattern
 var glob = Glob.Parse("p?th/*a[bcd]b[e-g]a[1-4][!wxyz][!a-c][!1-3].*");
 var isMatch = glob.IsMatch("pAth/fooooacbfa2vd4.txt");

Build a glob fluently

You can also use the GlobBuilder class if you wish to build up a glob using a fluent syntax.
This is also more efficient as it avoids having to parse the glob from a string pattern.

So to build the following glob pattern: /foo?\\*[abc][!1-3].txt:


  var glob = new GlobBuilder()
                .PathSeperator()
                .Literal("foo")
                .AnyCharacter()
                .PathSeperator(PathSeperatorKind.BackwardSlash)
                .Wildcard()
                .OneOf('a', 'b', 'c')
                .NumberNotInRange('1', '3')
                .Literal(".txt")
                .ToGlob();

   var isMatch = glob.IsMatch(@"/fooa\\barrra4.txt"); // returns true.

Patterns

The following patterns are supported (from wikipedia):

| Wildcard | Description | Example | Matches | Does not match |
| -------- | ----------- | ------- | ------- | -------------- |
| * | matches any number of any characters including none | Law*| Law, Laws, or Lawyer |
| ? | matches any single character | ?at | Cat, cat, Bat or bat | at |
| [abc] | matches one character given in the bracket | [CB]at | Cat or Bat | cat or bat |
| [a-z] | matches one character from the range given in the bracket | Letter[0-9] | Letter0, Letter1, Letter2 up to Letter9 | Letters, Letter or Letter10 |
| [!abc] | matches one character that is not given in the bracket | [!C]at | Bat, bat, or cat | Cat |
| [!a-z] | matches one character that is not from the range given in the bracket | Letter[!3-5] | Letter1, Letter2, Letter6 up to Letter9 and Letterx etc. | Letter3, Letter4, Letter5 or Letterxx |

In addition, DotNet Glob also supports:

| Wildcard | Description | Example | Matches | Does not match |
| -------- | ----------- | ------- | ------- | -------------- |
| ** | matches any number of path / directory segments. When used must be the only contents of a segment. | /**/some.* | /foo/bar/bah/some.txt, /some.txt, or /foo/some.txt |

Advanced Usages

Parsing options.

By default, when your glob pattern is parsed, DotNet.Glob will only allow literals which are valid for path / directory names.
These are:

  1. Any Letter (A-Z, a-z) or Digit
  2. ., , !, #, -, ;, =, @, ~, _, :

This is optimised for matching against paths / directory strings.
However, introduced in version 1.6.4, you can override this behaviour so that you can include arbitrary characters in your literals. For example, here is a pattern that matches the literal &quot;Stuff:

    // Overide the default options globally for all matche:
    GlobParseOptions.Default.Parsing.AllowInvalidPathCharacters = true;
    DotNet.Globbing.Glob.Parse("\"Stuff*").IsMatch("\"Stuff"); // true;    

You can also just set these options on a per glob pattern basis:

    GlobOptions options = new GlobOptions();
    options.Parsing.AllowInvalidPathCharacters = allowInvalidPathCharcters;
    DotNet.Globbing.Glob.Parse("\"Stuff*", globParseOptions).IsMatch("\"Stuff"); // true; 

Case Sensitivity (Available as of version >= 2.0.0)

By default, evaluation is case-sensitive unless you specify otherwise.

    GlobOptions options = new GlobOptions();
    options.Evaluation.CaseInsensitive = true;
    DotNet.Globbing.Glob.Parse("foo*", globParseOptions).IsMatch("FOo"); // true; 

Setting CaseInsensitive has an impact on:

  • Letter Ranges. Any letter range (i.e '[A-Z]') will now match both lower or upper case characters.
  • Character Lists. Any character list (i.e '[ABC]') will now match both lower or upper case characters.
  • Literals. Any literal (i.e 'foo') will now match both lower or upper case characters i.e FoO will match foO etc.

Match Generation

Given a glob, you can generate random matches, or non matches, for that glob.
For example, given the glob pattern /f?o/bar/**/*.txt you could generate matching strings like /foo/bar/ajawd/awdaw/adw-ad.txt or random non matching strings.

  var dotnetGlob = Glob.Parse(pattern);
  var generator = new GlobMatchStringGenerator(dotnetGlob.Tokens);

  for (int i = 0; i < 10; i++)
  {
          var testString = generator.GenerateRandomMatch();
          var result = dotnetGlob.IsMatch(testString);
          // result is always true.

          // generate a non match.
          testString = generator.GenerateRandomNonMatch();
          var result = dotnetGlob.IsMatch(testString);
           // result is always false.
  }

Release Notes

New features and fixes. See README in Github Repo.

  • .NETFramework 4.0

    • No dependencies.
  • .NETFramework 4.5

    • No dependencies.
  • .NETFramework 4.6

    • No dependencies.
  • .NETStandard 1.1

GitHub repositories (3)

Showing the top 3 popular GitHub repositories that depend on DotNet.Glob:

Repository Stars
jellyfin/jellyfin
The Free Software Media System
hvanbakel/CsprojToVs2017
Tooling for converting pre 2017 project to the new Visual Studio 2017 format.
stryker-mutator/stryker-net
Mutation testing for .NET core and .NET framework!

Version History

Version Downloads Last updated
3.1.0-issue-75.1 84 5/24/2020
3.1.0-alpha0009 20,377 8/3/2019
3.1.0-alpha0004 901 3/24/2019
3.1.0-alpha.49 59 5/24/2020
3.1.0-alpha.47 68 3/5/2020
3.0.9 16,063 3/5/2020
3.0.9-beta.1 55 3/5/2020
3.0.8-beta0001 192 2/22/2020
3.0.5 68,483 4/2/2019
3.0.2-beta0001 170 4/2/2019
3.0.1 9,817 3/24/2019
3.0.1-beta0001 151 3/24/2019
3.0.0-alpha0052 170 3/24/2019
3.0.0-alpha0048 161 3/24/2019
3.0.0-alpha0045 182 2/11/2019
3.0.0-alpha0043 278 12/15/2018
3.0.0-alpha0041 1,124 9/12/2018
2.2.0-alpha0002 204 9/11/2018
2.2.0-alpha0001 217 8/24/2018
2.1.4 371 4/2/2019
2.1.3 186 3/24/2019
2.1.3-beta0001 181 3/24/2019
2.1.1 51,528 9/12/2018
2.1.0 1,810 8/24/2018
2.1.0-escaping0001 272 8/15/2018
2.1.0-alpha0034 194 8/24/2018
2.1.0-alpha0033 216 8/24/2018
2.1.0-alpha0022 289 8/10/2018
2.1.0-alpha0020 485 4/27/2018
2.0.3 43,566 4/27/2018
2.0.3-beta0001 336 4/27/2018
2.0.2 345 4/27/2018
2.0.1 97,616 3/27/2018
2.0.0 3,781 3/20/2018
2.0.0-alpha0139 380 3/11/2018
2.0.0-alpha0137 365 3/11/2018
2.0.0-alpha0130 340 3/11/2018
2.0.0-alpha0128 339 3/11/2018
2.0.0-alpha0127 367 3/11/2018
2.0.0-alpha0126 323 3/11/2018
2.0.0-alpha0125 334 3/11/2018
2.0.0-alpha0124 346 3/11/2018
2.0.0-alpha0123 336 3/11/2018
2.0.0-alpha0122 376 3/11/2018
2.0.0-alpha0121 342 3/11/2018
2.0.0-alpha0116 607 12/22/2017
2.0.0-alpha0115 378 12/22/2017
1.7.0-unstable0022 579 9/6/2017
1.7.0-unstable0018 337 8/27/2017
1.7.0-unstable0017 339 8/27/2017
1.7.0-unstable0013 377 7/12/2017
1.7.0-unstable0012 367 7/12/2017
1.7.0-unstable0009 423 6/30/2017
1.7.0-unstable0004 351 6/6/2017
1.7.0-unstable0001 346 5/18/2017
1.7.0-alpha0033 513 10/2/2017
1.6.9 3,558 10/2/2017
1.6.6 900 9/6/2017
1.6.5 503 8/27/2017
1.6.4 27,303 7/12/2017
1.6.3 449 6/30/2017
1.6.1 374 6/6/2017
1.6.0 1,945 5/18/2017
1.6.0-unstable0003 330 5/18/2017
1.6.0-unstable0002 353 5/12/2017
1.6.0-unstable0001 550 5/5/2017
1.5.0 359 5/5/2017
1.5.0-unstable0028 373 5/5/2017
1.5.0-unstable0027 358 5/5/2017
1.5.0-unstable0014 376 3/6/2017
1.5.0-unstable0013 351 3/6/2017
1.5.0-unstable0011 423 1/7/2017
1.5.0-unstable0010 407 1/5/2017
1.5.0-unstable0007 404 1/5/2017
1.5.0-unstable0006 433 12/19/2016
1.5.0-unstable0005 416 12/17/2016
1.5.0-unstable0001 433 12/15/2016
1.4.2 1,131 1/5/2017
1.4.1 1,700 12/17/2016
1.4.0 421 12/15/2016
1.4.0-unstable0004 403 12/15/2016
1.4.0-unstable0002 419 12/15/2016
1.4.0-unstable0001 438 12/14/2016
1.3.0 445 12/14/2016
1.3.0-unstable0021 393 12/12/2016
1.3.0-unstable0019 408 12/12/2016
1.3.0-unstable0018 405 12/12/2016
1.3.0-unstable0017 377 12/11/2016
1.3.0-unstable0016 381 12/11/2016
1.3.0-unstable0015 448 12/11/2016
1.3.0-unstable0014 452 12/10/2016
1.3.0-unstable0010 486 12/10/2016
1.3.0-unstable0008 468 12/10/2016
1.3.0-unstable0004 397 12/9/2016
1.3.0-unstable0002 454 12/9/2016
1.2.2 451 12/10/2016
1.2.1 453 12/9/2016
1.2.0-unstable0001 440 12/9/2016
1.1.0 471 12/9/2016
1.1.0-unstable0008 456 12/9/2016
1.1.0-unstable0005 440 12/7/2016
1.1.0-unstable0002 368 12/7/2016
1.1.0-unstable0001 440 12/7/2016
1.0.1 444 12/7/2016
1.0.0 446 12/7/2016
0.1.0 478 12/7/2016
0.1.0-unstable0012 434 12/7/2016
Show less