Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check if a filename matches a wildcard pattern? [duplicate]

Tags:

.net

I know I can do

Directory.GetFiles(@"c:\", "*.html")

and I'll get a list of files that match the *.html file pattern.

I'd like to do the inverse. Given file name abc.html, I'd like a method that will tell me if that filename matches the *.html pattern. for instance

class.method("abc.html", "*.html") // returns true
class.method("abc.xml", "*.html") // returns false
class.method("abc.doc", "*.?oc") // returns true
class.method("Jan24.txt", "Jan*.txt") // returns true
class.method("Dec24.txt", "Jan*.txt") // returns false

The functionality must exist in dotnet. I just don't know where it's exposed.

Converting the pattern to regex could be one way to go. However it just seems like there are a lot of edge cases and may be more trouble than it's worth.

Note: the filename in questions may not exist yet, so I can't just wrap a Directory.GetFiles call and check to see if the result set has any entries.

like image 280
Aheho Avatar asked Jan 29 '26 07:01

Aheho


1 Answers

Easiest way to go is to convert your wildcard to regex, and then apply it:

public static string WildcardToRegex(string pattern)
{
  return "^" + Regex.Escape(pattern).
  Replace("\\*", ".*").
  Replace("\\?", ".") + "$";
}

But if you cannot use regex for some reason, you can write your own implementation of wildcard matching. You can find one here.

Here's another one ported from python implementation (Edit 2020-07: fixed IndexOutOfRangeException):

using System;
    
class App
{
  static void Main()
  {
    Console.WriteLine(Match("abc.html", "*.html")); // returns true
    Console.WriteLine(Match("abc.xml", "*.html")); // returns false
    Console.WriteLine(Match("abc.doc", "*.?oc")); // returns true
    Console.WriteLine(Match("Jan24.txt", "Jan*.txt")); // returns true
    Console.WriteLine(Match("Dec24.txt", "Jan*.txt")); // returns false  
  }
    
  static bool Match(string s1, string s2)
  {
    if (s2=="*" || s1==s2) return true;
    if (s1=="" || s2=="") return false;

    if (s1[0]==s2[0] || s2[0]=='?') return Match(s1.Substring(1),s2.Substring(1));
    if (s2[0]=='*') return Match(s1.Substring(1),s2) || Match(s1,s2.Substring(1));
    return false;
  }
}
like image 72
Alexander Avatar answered Jan 30 '26 22:01

Alexander