Pregunta

I'm trying to search for specific file name on all volumes on the system, except System Volume Information or Windows Directories and print out every full path for each file.

I've tried to use Directory.GetFiles, but it only searche inside Drive C:\ or Drive D:\ (depends which drive is specified)

How can I achieve my goal?

For example I want to run program and search for file with name ".DS_Store" (used to use mac, and now my file system is full of these files....)

I would really appreciate any help. Thank you in advance

UPD. Program Should be executed with Admin rights to work

¿Fue útil?

Solución

As part of a cryptolocker analysis, I wrote a prototype that locates target extensions, here is how to use it

var cmd = new LocateTargetFilesCommand();
cmd.Execute()

It will search all the drives for two extensions: .xlsx and .doc. The biggest problem is to handle permissions issue. Also a child folder may have wider permissions, so if you cannot access a parent folder, you can still potentially access its roots.

At the end, cmd.FoundTargets will contain absolute paths to the found files with desired extensions

public class LocateTargetFilesCommand 
{
    private string[] _targetExtensions = new[]
        {
            "xlsx", "doc"
        };

    public LocateTargetFilesCommand()
    {
        FoundTargets = new ConcurrentQueue<string>();
        DirsToSearch = new List<string>();
    }

    public ConcurrentQueue<string> FoundTargets { get; private set; }
    public List<string> DirsToSearch { get; private set; }

    public void Execute()
    {
        DriveInfo[] driveInfos = DriveInfo.GetDrives();

        Console.WriteLine("Start searching");
        foreach (var driveInfo in driveInfos)
        {

            if (!driveInfo.IsReady)
                continue;

            Console.WriteLine("Locating directories for drive: " + driveInfo.RootDirectory);
            GetAllDirs(driveInfo.RootDirectory.ToString());
            Console.WriteLine("Found {0} folders", DirsToSearch.Count);

            foreach (var ext in _targetExtensions)
            {
                Console.WriteLine("Searching for .*" + ext);

                int currentNotificationProgress = 0;
                for (int i = 0; i < DirsToSearch.Count; i++)
                {
                    int progressPercentage = (i * 100) / DirsToSearch.Count;
                    if (progressPercentage != 0)
                    {
                        if (progressPercentage % 10 == 0 && currentNotificationProgress != progressPercentage)
                        {
                            Console.WriteLine("Completed {0}%", progressPercentage);
                            currentNotificationProgress = progressPercentage;
                        }
                    }

                    var dir = DirsToSearch[i];
                    try
                    {
                        string[] files = Directory.GetFiles(dir, "*." + ext, SearchOption.TopDirectoryOnly);
                        foreach (var file in files)
                        {
                            FoundTargets.Enqueue(file);
                        }
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        Console.WriteLine("Skipping directory: {0}", dir);
                        DirsToSearch.Remove(dir);
                    }
                }

                Console.WriteLine("So far located {0} targets", FoundTargets.Count);
            }

            DirsToSearch.Clear();
        }

        Console.WriteLine("Stop searching");
    }

    public void GetAllDirs(string root)
    {
        try
        {
            string[] dirs = Directory.GetDirectories(root);
            DirsToSearch.AddRange(dirs);
            foreach (var dir in dirs)
            {
                GetAllDirs(dir);
            }
        }
        catch (UnauthorizedAccessException)
        {
            //swallow
        }
    }
}

Otros consejos

Use GetLogicalDrives

foreach (var d in Directory.GetLogicalDrives())
{         
     var files = Directory.GetFiles(d, file);         
}

Try this:

foreach (var drive in Directory.GetLogicalDrives())
{
    foreach (var fileInfo in from dir in Directory.GetDirectories(drive) from file in Directory.GetFiles(dir) select new FileInfo(file))
    {
        // get all details in fileInfo
    }
}

Thanks to oleksii, but here is how I used this code to exclude all System directories:

public class LocateTargetFilesCommand
{
    private string[] _targetExtensions = new[]
    {
        ".DS_Store"
    };

    public LocateTargetFilesCommand()
    {
        FoundTargets = new ConcurrentQueue<string>();
        DirsToSearch = new List<string>();
    }

    public ConcurrentQueue<string> FoundTargets { get; private set; }
    public List<string> DirsToSearch { get; private set; }

    public void Execute()
    {
        DriveInfo[] driveInfos = DriveInfo.GetDrives();

        Console.WriteLine("Start searching");
        foreach (var driveInfo in driveInfos)
        {
            if (!driveInfo.IsReady)
                continue;

            Console.WriteLine("Locating directories for drive: " + driveInfo.RootDirectory);
            GetAllDirs(driveInfo.RootDirectory.ToString());
            Console.WriteLine("Found {0} folders", DirsToSearch.Count);

            foreach (var ext in _targetExtensions)
            {
                Console.WriteLine("Searching for " + ext);

                int currentNotificationProgress = 0;
                for (int i = 0; i < DirsToSearch.Count; i++)
                {
                    int progressPercentage = (i * 100) / DirsToSearch.Count;
                    if (progressPercentage != 0)
                    {
                        if (progressPercentage % 10 == 0 && currentNotificationProgress != progressPercentage)
                        {
                            Console.WriteLine("Completed {0}%", progressPercentage);
                            currentNotificationProgress = progressPercentage;
                        }
                    }

                    var dir = DirsToSearch[i];
                    try
                    {
                        string[] files = Directory.GetFiles(dir, ext, SearchOption.TopDirectoryOnly);
                        foreach (var file in files)
                        {
                            FoundTargets.Enqueue(file);
                        }
                    }
                    catch (UnauthorizedAccessException ex)
                    {
                        Console.WriteLine("Skipping directory: {0}", dir);
                        DirsToSearch.Remove(dir);
                    }
                }

                Console.WriteLine("So far located {0} targets", FoundTargets.Count);
            }

            DirsToSearch.Clear();
        }

        Console.WriteLine("Stop searching");
    }

    public void GetAllDirs(string root)
    {
        try
        {
            string[] dirs = Directory.GetDirectories(root);
            DirsToSearch.AddRange(dirs);
            foreach (var dir in dirs)
            {   
                if(dir.Contains("Windows"))
                    Console.WriteLine("Skipped Windows Directory");
                else if (dir.Contains("Users"))
                    Console.WriteLine("Skipped Users Directory");
                else if (dir.Contains("MSOCache"))
                    Console.WriteLine("Skipped MSOCache Directory");
                else if (dir.Contains("SYSTEM.SAV"))
                    Console.WriteLine("Skipped SYSTEM.SAV Directory");
                else if (dir.Contains("ProgramData"))
                    Console.WriteLine("Skipped ProgramData Directory");
                else if (dir.Contains("System Volume Information"))
                    Console.WriteLine("Skipped System Volume Information Directory");
                else if (dir.Contains("$SysReset"))
                    Console.WriteLine("Skipped $SysReset Directory");
                else
                    GetAllDirs(dir);
            }
        }
        catch (UnauthorizedAccessException)
        {

        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top