2

Does anyone know if there's an equivalent functionality to the Windows API function PathMatchSpec() in .NET?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
dcw
  • 3,481
  • 2
  • 22
  • 30

4 Answers4

1

I'm not aware of a method built in to .NET however it's trivial to duplicate with a Regex:

public static bool PathMatchSpec(String path, String spec)
{
    String specAsRegex = Regex.Escape(spec).Replace("\\*", ".*").Replace("\\?", ".") + "$";
    return Regex.IsMatch(path, specAsRegex);
}

Obviously this assumes the System.Text.RegularExpressions namespace is referenced. If you're going to do this alot with the same spec you could cache the Regex as well.

EDIT TO ADD: P/Invoke is indeed an option, but the signature for PathMatchSpec indicates it takes an ANSI string, so you'd be incurring a character set conversion for each invocation. Keep that in mind if you go that route. In that case PathMatchSpecEx would probably be preferable.

anelson
  • 2,569
  • 1
  • 19
  • 30
  • Cool... didn't know of the Escape() method myself; would definitely simplify part of my solution ;) – jerryjvl Jun 05 '09 at 06:15
0

If you can't get the functionality using Regular Expressions (I believe this is the case) how about using PathMatchSpec() through PInvoke?

http://www.pinvoke.net/default.aspx/shlwapi/PathMatchSpec.html

Jay Riggs
  • 53,046
  • 9
  • 139
  • 151
0

You can try How to implement glob in C# or of course there's the PInvoke route if necessary.

Community
  • 1
  • 1
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
0

In short... not that I know of... but maybe this can help you along (note, a bit lengthier than you might want, but it has served me well):

sealed public class WildcardMatch
{
    private static Regex wildcardFinder = new Regex(@"(?<wildcards>\?+|\*+)", RegexOptions.Compiled | RegexOptions.Singleline);
    private Regex wildcardRegex;

    public WildcardMatch(string wildcardFormat) : this(wildcardFormat, false) { }

    public WildcardMatch(string wildcardFormat, bool ignoreCase)
    {
        if (wildcardFormat == null)
            throw new ArgumentNullException("wildcardFormat");

        StringBuilder patternBuilder = new StringBuilder("^");
        MatchCollection matches = this.wildcardFinder.Matches(wildcardFormat);
        string[] split = this.wildcardFinder.Split(wildcardFormat);
        for (int ix = 0; ix < split.Length; ix++)
        {
            // Even indexes are literal text, odd indexes correspond to matches
            if (ix % 2 == 0)
                patternBuilder.Append(Regex.Escape(split[ix]));
            else
            {
                // Matches must be substituted with Regex control characters
                string wildcards = matches[ix / 2].Groups["wildcards"].Value;
                if (wildcards.StartsWith("*", StringComparison.Ordinal))
                    patternBuilder.Append("(.*)");
                else
                    patternBuilder.AppendFormat(CultureInfo.InvariantCulture, "({0})", wildcards.Replace('?', '.'));
            }
        }
        patternBuilder.Append("$");

        this.wildcardRegex = new Regex(
            patternBuilder.ToString(),
            RegexOptions.Singleline | (ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None));
    }

    public bool IsMatch(string value)
    {
        if (value == null)
            return false;

        return this.wildcardRegex.IsMatch(value);
    }

    public IEnumerable<string> ExtractMatches(string value)
    {
        if (value == null)
            yield break;

        Match match = this.wildcardRegex.Match(value);
        if (!match.Success)
            yield break;

        for (int ix = 1; ix < match.Groups.Count; ix++)
            yield return match.Groups[ix].Value;
    }
}
jerryjvl
  • 19,723
  • 7
  • 40
  • 55