0

how can I resolve the wildcard * char if is used in source path.

Input parameter explained in below example :

For example, C:\Owners*\App*\Temp* resolves as:

C:\Owners\User1\App\Local\Temp*

C:\Owners\User1\App\LocalDir\Temp*

C:\Owners\User1\App\Roam\Temp*

C:\Owners\User2\App\Local\Temp*

C:\Owners\User2\App\LocalDir\Temp*

C:\Users\User2\App\Roaming\Temp*

File delete and directory delete can be done but I am unable to resolve the path when it contains wildcard char as *.

  • Filename wildcard is ok. But what is wildcard in path name? You cannot change directory with `*` in path. – i486 May 29 '23 at 08:37

1 Answers1

0

Do you want to process a path that contains wildcards and delete found folders/files? As far as I know, there are currently no methods that allow wildcards to be used in any part of the path. So I wrote my method:

/// <summary>
/// Parse path that may contain wildcards
/// </summary>
/// <param name="pathWithWildcards">The pattern by which we are looking for files/folders</param>
/// <param name="isFolder">Looking for folders or files?</param>
/// <returns>List of paths that match the specified pattern</returns>
public static List<string> ParsePath(string pathWithWildcards, bool isFolder = false)
{
    if (string.IsNullOrEmpty(pathWithWildcards)) return new List<string>(0);
    if (!pathWithWildcards.Any(x => x == '*' || x == '?')) return new List<string> { pathWithWildcards };
    if (!pathWithWildcards.Contains(':'))
    {
        string[] pathParts = pathWithWildcards.Split('\\');
        pathParts[0] = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, pathParts[0]).TrimEnd('\\');
        pathWithWildcards = string.Join("\\", pathParts);
    }

    List<string> paths = new List<string>();
    List<string> patterns = new List<string> { pathWithWildcards };
    while (patterns.Count > 0)
    {
        string[] pathParts = patterns[0].Split('\\');
        for (int i = 0; i < pathParts.Length; i++)
        {
            if (!pathParts[i].Any(x => x == '*' || x == '?')) continue;
            string firstPart = string.Join("\\", pathParts.Take(i)) + "\\";
            string lastPart = pathParts.Length > i + 1 ? string.Join("\\", pathParts.Skip(i + 1)) : string.Empty;
            if (!Directory.Exists(firstPart))
            {
                patterns.RemoveAt(0);
                break;
            }
            bool isFinalAndFile = lastPart.Length == 0 && !isFolder;
            string[] search = isFinalAndFile ?
                Directory.GetFiles(firstPart, pathParts[i]) :
                Directory.GetDirectories(firstPart, pathParts[i]);
            if (lastPart.Length > 0) search = search.Select(x => Path.Combine(x, lastPart)).ToArray();
            IEnumerable<string> withPattern = search.Where(x => x.Any(y => y == '*' || y == '?'));
            patterns.AddRange(withPattern);
            paths.AddRange(search.Except(withPattern).Where(x => isFinalAndFile ? File.Exists(x) : Directory.Exists(x)));
            patterns.RemoveAt(0);
            break;
        }
    }

    return paths;
}

Usage example:

Stopwatch sw = new Stopwatch();

string path1 = "C:\\Users\\*\\AppData\\*\\Ad?be\\Color";
sw.Start();
List<string> test1 = ParsePath(path1, true);
Console.WriteLine($"Found: {test1.Count} folder(s)\nElapsed time: {sw.ElapsedMilliseconds} ms\nList:");
test1.ForEach(f => Console.WriteLine(f));

string path2 = "C:\\Users\\*\\AppData\\*\\Ad?be\\Color\\ACE*.lst";
sw.Restart();
List<string> test2 = ParsePath(path2);
Console.WriteLine($"Found: {test2.Count} file(s)\nElapsed time: {sw.ElapsedMilliseconds} ms\nList:");
test2.ForEach(f => Console.WriteLine(f));

string path3 = "*\\test (*).txt";
sw.Restart();
List<string> test3 = ParsePath(path3);
Console.WriteLine($"Found: {test3.Count} file(s)\nElapsed time: {sw.ElapsedMilliseconds} ms\n");

// Output:

// Found: 2 folder(s)
// Elapsed time: 13 ms
// List:
// C:\Users\Andrew\AppData\Local\Adobe\Color
// C:\Users\Andrew\AppData\Roaming\Adobe\Color

// Found: 2 file(s)
// Elapsed time: 2 ms
// List:
// C:\Users\Andrew\AppData\Local\Adobe\Color\ACECache11.lst
// C:\Users\Andrew\AppData\Roaming\Adobe\Color\ACEConfigCache2.lst

// Found: 2000 file(s)
// Elapsed time: 105 ms

Found folders/files can be deleted immediately, but I advise you to do this only if you are completely sure of your pattern. Otherwise, you may accidentally delete important data

ParsePath("Test folder\\*\\*.txt").ForEach(f => File.Delete(f));
ParsePath("Test folder\\*", true).ForEach(f => Directory.Delete(f));
Qustux
  • 11
  • 1