C
C#•3y ago
Drajzer

āœ… Searching for all possible files with .txt extension

How i can search for all .txt files on all drives ?
10 Replies
Drajzer
DrajzerOP•3y ago
Or i can search on one drive and then do it for another one but how
Thinker
Thinker•3y ago
Directory.GetFiles("C:/", "*.txt", new EnumerationOptions() { RecurseSubdirectories = true })
Directory.GetFiles("C:/", "*.txt", new EnumerationOptions() { RecurseSubdirectories = true })
Although this is very likely to cause access violation exceptions and take a very long time
Drajzer
DrajzerOP•3y ago
i have this
public List<string> Search()
{
var files = new List<string>();
foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady))
{
try
{
files.AddRange(Directory.GetFiles(d.RootDirectory.FullName, "*.txt", SearchOption.AllDirectories));
}
catch(Exception e)
{
Logger.Log(e.Message); // Log it and move on
}
}

return files;
}
public List<string> Search()
{
var files = new List<string>();
foreach (DriveInfo d in DriveInfo.GetDrives().Where(x => x.IsReady))
{
try
{
files.AddRange(Directory.GetFiles(d.RootDirectory.FullName, "*.txt", SearchOption.AllDirectories));
}
catch(Exception e)
{
Logger.Log(e.Message); // Log it and move on
}
}

return files;
}
mtreit
mtreit•3y ago
You are almost certainly going to hit an access denied exception on at least some path somewhere on the drive so I don't think that code is going to work.
Drajzer
DrajzerOP•3y ago
it wont i need help idk i can try catch but idk
mtreit
mtreit•3y ago
Here is a sketch of how I might approach it:
if (args.Length < 2)
{
Console.WriteLine("Usage:");
Console.WriteLine("Program.exe <rootPath> <searchPattern>");
return;
}

var files = FindFiles(args[0], args[1]);

foreach (var file in files)
{
Console.WriteLine(file);
}

IEnumerable<string> FindFiles(string rootPath, string searchPattern)
{
var queue = new Queue<string>();
queue.Enqueue(rootPath);

while (queue.Count > 0)
{
var current = queue.Dequeue();

try
{
foreach (var dir in Directory.EnumerateDirectories(current))
{
queue.Enqueue(dir);
}
}
catch (Exception e)
{
Console.WriteLine($"Skipping {current} due to error: {e.Message}.");
continue;
}

foreach (var file in Directory.EnumerateFiles(current, searchPattern))
{
yield return file;
}
}
}
if (args.Length < 2)
{
Console.WriteLine("Usage:");
Console.WriteLine("Program.exe <rootPath> <searchPattern>");
return;
}

var files = FindFiles(args[0], args[1]);

foreach (var file in files)
{
Console.WriteLine(file);
}

IEnumerable<string> FindFiles(string rootPath, string searchPattern)
{
var queue = new Queue<string>();
queue.Enqueue(rootPath);

while (queue.Count > 0)
{
var current = queue.Dequeue();

try
{
foreach (var dir in Directory.EnumerateDirectories(current))
{
queue.Enqueue(dir);
}
}
catch (Exception e)
{
Console.WriteLine($"Skipping {current} due to error: {e.Message}.");
continue;
}

foreach (var file in Directory.EnumerateFiles(current, searchPattern))
{
yield return file;
}
}
}
Probably want a try-catch around the EnumerateFiles call as well, exercise left to the reader.
canton7
canton7•3y ago
Any reason to go breadth-first rather than depth-first? That feels like it'll end up adding lots of dirs to the queue, while the max folder depth doesn't tend to be that large
mtreit
mtreit•3y ago
Not really, just what I did off the top of my head
if (args.Length < 2)
{
Console.WriteLine("Usage:");
Console.WriteLine("Program.exe <rootPath> <searchPattern>");
return;
}

var files = FindFiles(args[0], args[1]);

foreach (var file in files)
{
Console.WriteLine(file);
}

IEnumerable<string> FindFiles(string rootPath, string searchPattern)
{
var stack = new Stack<string>();
stack.Push(rootPath);

while (stack.Count > 0)
{
var current = stack.Pop();

try
{
foreach (var dir in Directory.EnumerateDirectories(current))
{
stack.Push(dir);
}
}
catch (Exception e)
{
Console.WriteLine($"Skipping {current} due to error: {e.Message}.");
continue;
}

foreach (var file in Directory.EnumerateFiles(current, searchPattern))
{
yield return file;
}
}
}
if (args.Length < 2)
{
Console.WriteLine("Usage:");
Console.WriteLine("Program.exe <rootPath> <searchPattern>");
return;
}

var files = FindFiles(args[0], args[1]);

foreach (var file in files)
{
Console.WriteLine(file);
}

IEnumerable<string> FindFiles(string rootPath, string searchPattern)
{
var stack = new Stack<string>();
stack.Push(rootPath);

while (stack.Count > 0)
{
var current = stack.Pop();

try
{
foreach (var dir in Directory.EnumerateDirectories(current))
{
stack.Push(dir);
}
}
catch (Exception e)
{
Console.WriteLine($"Skipping {current} due to error: {e.Message}.");
continue;
}

foreach (var file in Directory.EnumerateFiles(current, searchPattern))
{
yield return file;
}
}
}
There šŸ™‚ Alternate version I guess you would want to call Reverse() on Directory.EnumerateDirectories() if you want the same order you would get if you did something like Get-ChildItem -Recurse (i.e., dir /s)
Drajzer
DrajzerOP•3y ago
thank you lot of ā¤ļø but i cant access Desktop and Documents,i can access if im going first in directory and list files then get files name but with that code i cant im running .exe as admin
DirectoryInfo place = new DirectoryInfo(@"C:\Users\*****\Desktop");
FileInfo[] fls = place.GetFiles();
Console.WriteLine("DESKTOP: ");
foreach(FileInfo i in fls)
{
Console.WriteLine(i.Name);
}
DirectoryInfo place = new DirectoryInfo(@"C:\Users\*****\Desktop");
FileInfo[] fls = place.GetFiles();
Console.WriteLine("DESKTOP: ");
foreach(FileInfo i in fls)
{
Console.WriteLine(i.Name);
}
like this i can create list return it but is there way to dont do like that and access it with ur code
Accord
Accord•3y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.

Did you find this page helpful?