TheSwamp
Code Red => .NET => Topic started by: Kerry on December 19, 2008, 09:09:46 PM
-
FindFile in the net API is handy ... as it is in lisp ... but the limiting search folders is sometimes a restraint
... think of the case where you know the file you want is nested in a tree structure and because of dynamics you may not know the location.
This code is beta, but seems to do the job.
This is the tree I'm looking at .. the tree structure is dynamic but I know the file I want is in there somewhere.
(http://www.theswamp.org/screens/index.php?dir=KerryBrown/&file=FindFileRecursion01.png)
First try a findfile with the qualified Path
Then some recursion variations ..
[CommandMethod("Cmd2")]
static public void test2()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
string fileName = @"F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Squircle.dwg";
ed.WriteMessage("\n\n ----------- FindFile(... " );
string qualifiedPath = HostApplicationServices.Current.
FindFile(fileName, db, FindFileHint.Default);
if (string.IsNullOrEmpty(qualifiedPath))
{
ed.WriteMessage("\nOooops, Can't find file " + fileName);
} else
{
ed.WriteMessage("\nFile Found at " + qualifiedPath);
}
/////
ed.WriteMessage("\n\n ----------- FindFilesRecursive(... " + "*.*" );
List<string> fileList1 = FindFilesRecursive(@"F:\_kdub_testing", "*.*");
foreach (string s in fileList1)
{
ed.WriteMessage("\n" + s);
}
/////
ed.WriteMessage("\n\n ----------- FindFilesRecursive(... " + "*.txt" );
List<string> fileList2 = FindFilesRecursive(@"F:\_kdub_testing", "*.txt");
foreach (string s in fileList2)
{
ed.WriteMessage("\n" + s);
}
/////
ed.WriteMessage("\n\n ----------- FindFilesRecursive(... " + "*nest*" );
List<string> fileList3 = FindFilesRecursive(@"F:\_kdub_testing", "*nest*");
foreach (string s in fileList3)
{
ed.WriteMessage("\n" + s);
}
/////
ed.WriteMessage("\n\n ----------- FindFilesRecursive(... " + "Squircle.dwg" );
List<string> fileList4 = FindFilesRecursive(@"F:\_kdub_testing", "*Squircle.dwg");
foreach (string s in fileList4)
{
ed.WriteMessage("\n" + s);
}
/////
ed.WriteMessage("\n\n ----------- FindFilesRecursive(... " + "SQUIRCLE.dwg" );
List<string> fileList5 = FindFilesRecursive(@"F:\_kdub_testing", "SQUIRCLE.dwg");
foreach (string s in fileList5)
{
ed.WriteMessage("\n" + s);
}
/////
}
static List<string> FindFilesRecursive(string initialFolder, string searchPattern)
{
// declare the file results list.
List<string> resultList = new List<string>();
// declare dynamic stack of folders.
Stack<string> folderStack = new Stack<string>();
// Add initialFolder to stack.
folderStack.Push(initialFolder);
// while there are Folders and child-Folders on the stack ...
while (folderStack.Count > 0)
{
// remove the top Folder name from the stack and
// see what the folder contains ....
string dir = folderStack.Pop();
try
{
// Add all files for/in this folder to the result List.
resultList.AddRange(Directory.GetFiles(dir, searchPattern));
// Add all sub-folders for/in this folder to the Stack.
foreach (string dn in Directory.GetDirectories(dir))
{
folderStack.Push(dn);
}
} catch
{
// problem opening folder
}
}
return resultList;
}
... and the results ..
Command: netload
Command: cmd2
----------- FindFile(...
File Found at F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Squircle.dwg
----------- FindFilesRecursive(... *.*
F:\_kdub_testing\nest-0\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\cross.dwg
F:\_kdub_testing\nest-0\nest-03\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-035\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-035\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0342\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0342\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Squircle.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\squircle.txt
F:\_kdub_testing\nest-0\nest-03\nest-033\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-033\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0322\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0322\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0321\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0321\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-031\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-031\cross.dwg
F:\_kdub_testing\nest-0\nest-02\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\nest-02421\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\nest-02421\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0241\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0241\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-023\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-023\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\nest-0221\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\nest-0221\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-021\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-021\cross.dwg
F:\_kdub_testing\nest-0\nest-01\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\code .txt
F:\_kdub_testing\nest-0\nest-01\Copy nested stuff .txt
F:\_kdub_testing\nest-0\nest-01\cpuid.txt
F:\_kdub_testing\nest-0\nest-01\cross.dwg
F:\_kdub_testing\nest-0\nest-01\Shared Folder Test.txt
F:\_kdub_testing\nest-0\nest-01\nest-013\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\nest-013\cross.dwg
F:\_kdub_testing\nest-0\nest-01\nest-012\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\nest-012\cross.dwg
F:\_kdub_testing\nest-0\nest-01\nest-011\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\nest-011\cross.dwg
F:\_kdub_testing\Dwgs\SECT-HEAD-1R.dwg
----------- FindFilesRecursive(... *.txt
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\squircle.txt
F:\_kdub_testing\nest-0\nest-01\code .txt
F:\_kdub_testing\nest-0\nest-01\Copy nested stuff .txt
F:\_kdub_testing\nest-0\nest-01\cpuid.txt
F:\_kdub_testing\nest-0\nest-01\Shared Folder Test.txt
----------- FindFilesRecursive(... *nest*
F:\_kdub_testing\nest-0\nest-01\Copy nested stuff .txt
----------- FindFilesRecursive(... Squircle.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Squircle.dwg
----------- FindFilesRecursive(... SQUIRCLE.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Squircle.dwg
-
I 'spose I could try a LINQ Query as well .... :|
-
Nice work Kerry! 8-)
-
Thanks Dan.
Holidays are great .. plenty of research and play time :)
-
FindFile in the net API is handy ... as it is in lisp ... but the limiting search folders is sometimes a restraint
... think of the case where you know the file you want is nested in a tree structure and because of dynamics you may not know the location.
This code is beta, but seems to do the job.
Assuming you actually wanted a non-recursive version,
I suppose that works.
Otherwise, this (which I've been using for ages) can do it:
/// Recursive file finder
///
/// E.g: string files[] = FindFiles.Find( "d:\\MyDrawings", "*.dwg" );
///
public static class FindFiles
{
public static string[] Find( string folder, string pattern )
{
List<string> result = new List<string>();
Find( folder, pattern, result );
return result.ToArray();
}
private static void Find( string folder, string pattern, List<string> result )
{
result.AddRange( Directory.GetFiles( folder, pattern ) );
foreach( string directory in Directory.GetDirectories( folder ) )
Find( Path.Combine( folder, directory ), pattern, result );
}
}
-
Nice Tony!
I had heard a rumor that most code houses do not allow recursive functions in production code for fear of a stack overflow,
anyone know if this is true? Obviously though, recursion is sometimes the most elegant way to solve certain tasks. :mrgreen:
-
Thanks Tony, I'll have a play tonight ..
I assume the
/// E.g: string files[] = FindFiles.Find( "d:\\MyDrawings", "*.dwg" );
should be
/// E.g: string[] files = FindFiles.Find( "d:\\MyDrawings", "*.dwg" );
-
Nice Tony!
I had heard a rumor that most code houses do not allow recursive functions in production code for fear of a stack overflow,
anyone know if this is true? Obviously though, recursion is sometimes the most elegant way to solve certain tasks. :mrgreen:
Hi Dan.
The decision is usually linked to praticle use, e.g., if you have a folder
structure deep enough to overflow the stack in a simple case like that,
you'd be better off firing the IT management that allowed things to get
that way, and give the programmer that wrote the recursive function
that merely exposed the larger problem a raise and a promotion :lmao:
I use recursion quite a bit, but in all cases I am more than confident
it will never go deep enough to use up the stack, and I have yet to
see it happen.
Also, there are quite a few compilers that know how to optimize
properly-tail-recursive code, and output iterative code that does
the job. I don't believe that C# does it, but most LISP and Scheme
compilers do, so an unconditional mandate banning recursion with
no regards to what tools are used or whether they can optimize
tail-recusive, seems a bit silly.
-
I use this (sorry I'm way too lazy today to clean this up) for this thing http://www.theswamp.org/index.php?topic=10211.0
private bool refreshstuff(string thefoldername, TreeNode ParentNode)
{
bool keep = false;// used to keep track of keeping the node
try
{
if (count <= maxfolder)// only do this until we hit max count, otherwise stop
{
count++;
if (checkBox1.Checked)// subdirectories too?
{
string[] folderEntries = Directory.GetDirectories(thefoldername);// get the folders in 'thefoldername'
foreach (string curfolder in folderEntries) // for each folder process it recursivly (yay!)
{
TreeNode NextNode = ParentNode.Nodes.Add(curfolder);
if (!refreshstuff(curfolder, NextNode)) // see if refreshstuff says to keep things around
{
NextNode.Remove();
keep = keep | false;// i don't know why this is here... but i'm keeping it around anyway (shouldn't x | false == x)
}
else
{
keep = true; // we want to keep stuff because refreshstuff said so, so remember that
}
}
}
}
*Giant file filtering snip (date of last edit, user that last edited, file name pattern)*
else if (!err && checkBox1.Checked)// if we havenn't hit and error, and we do want to check subdirectories... but we have searched alittle too much let the user know
{
MessageBox.Show(Form1.ActiveForm, "too many subfolders! get more detailed", "errr", MessageBoxButtons.OK, MessageBoxIcon.Information);
err = true;// and keep track of this (don't want to be bombarded with errors
}
*some more snipage*
return keep;// let the calling function know what was found in the directory
} // the thinking refresh tree function (recursive fun)
-
and, because it's Monday and I'm home ....
a little LINQ
var InitialFolderList = new List<string> { @"F:\_kdub_testing"};
var dirQuery = InitialFolderList
.Where(dir => Directory.Exists(dir))
.SelectMany(dir =>
Directory.GetFiles( dir, "*.*", SearchOption.AllDirectories) );
var filesQuery = InitialFolderList
.Where(dir=> File.Exists(dir));
var SortedFileList = dirQuery.Union(filesQuery).OrderBy (s => s);
SortedFileList.Dump ("Ordered alphabetically");
F:\_kdub_testing\Dwgs\SECT-HEAD-1R.dwg
F:\_kdub_testing\nest-0\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\cross.dwg
F:\_kdub_testing\nest-0\nest-01\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\code .txt
F:\_kdub_testing\nest-0\nest-01\Copy nested stuff .txt
F:\_kdub_testing\nest-0\nest-01\cpuid.txt
F:\_kdub_testing\nest-0\nest-01\cross.dwg
F:\_kdub_testing\nest-0\nest-01\nest-011\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\nest-011\cross.dwg
F:\_kdub_testing\nest-0\nest-01\nest-012\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\nest-012\cross.dwg
F:\_kdub_testing\nest-0\nest-01\nest-013\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-01\nest-013\cross.dwg
F:\_kdub_testing\nest-0\nest-01\Shared Folder Test.txt
F:\_kdub_testing\nest-0\nest-02\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-021\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-021\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\nest-0221\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-022\nest-0221\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-023\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-023\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0241\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0241\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\cross.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\nest-02421\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-02\nest-024\nest-0242\nest-02421\cross.dwg
F:\_kdub_testing\nest-0\nest-03\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-031\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-031\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0321\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0321\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0322\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-032\nest-0322\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-033\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-033\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\Squircle.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0341\squircle.txt
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0342\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-034\nest-0342\cross.dwg
F:\_kdub_testing\nest-0\nest-03\nest-035\Alphabet Soup.dwg
F:\_kdub_testing\nest-0\nest-03\nest-035\cross.dwg
-
Alphabet Soup.dwg :laugh:
-
and, because it's Monday and I'm home ....
Monday? What UTM are you in? 10T for me.
Paul
-
Gender: yes
Age: Mesozoic
Location: Brisbane, Australia [ gmt +10 ]
Local Time: 2008-12-21, 14:00:45
-
Gender: yes
Age: Mesozoic
Location: Brisbane, Australia [ gmt +10 ]
Local Time: 2008-12-21, 14:00:45
Ha, not ASL, but thanks.
Seattle, WA gmt-8
20:06:00, 12-21-08
-
ok .. UTM is 56J
-
I’m in 17T but will be in 51R in February.
It's too cold in 17T :lol:
-
SearchOption.AllDirectories
From the docs: ''...follows symbolic links...', which is
microsoft-ese for 'follows shortcuts'.
IOW, when it finds a shortcut to a folder that was
already processed in a child of that folder, it will
process the parent folder again.
IOW, this option is dangerous because it can lead
to infinite recursion.
-
Dan,
that sounds like really bad poetry lyrics
-
WooahYa I’m down and out in 17T where the wind chill is -17°C :laugh:
-
SearchOption.AllDirectories
From the docs: ''...follows symbolic links...', which is
microsoft-ese for 'follows shortcuts'.
IOW, when it finds a shortcut to a folder that was
already processed in a child of that folder, it will
process the parent folder again.
IOW, this option is dangerous because it can lead
to infinite recursion.
First Time I've read that Tony ... and the SearchOption.AllDirectories has been around for a while ... surprised it's not plastered all over the web.
-
Actually, I think my translation of Microsoft-ese may have been
incorrect. Reparse points (like mapped drives) that can create a
circular or cyclical reference, is the problem, not shortcuts.
http://msdn.microsoft.com/en-us/library/ms143448.aspx
(See the remarks)
The following link also has some useful information on traversing
the file system, and other potential pitfalls like directory access
rights, and so on:
http://msdn.microsoft.com/en-us/library/bb513869.aspx
As far as 'stack-o-phobia' goes :D, the depth of recursion equals
the depth of folder nesting and from my calculations, unless there
are folders nested ~250 levels deep or more, I think recursion is
a safe approach. The use of the stack can also be minimized by
using non-static methods and storing the current folder in a non
static member variable, rather than passing it as an argument to
the recursive method (which is stored in each call's stack frame).
CLR 4.0 has tail-recursion optimization, but only for F#, by way of
that compiler. From what I've read, the problem with tail-recursion
optimization in .NET is that the security model relies heavily on call
stack introspection to detect the calling context of methods (e.g.,
examine the call stack to see who is calling your method), which
can preclude optimizing tail-recursive calls into iterative loops.
One reason that purely-recursive or functional approaches with no
side-effects are desirable for solving problems like this, is that they
are better suited for parallel execution (even though in this case,
disk I/O is the likely bottleneck and limiting factor).
A stack-based approach could not easily run on mutliple CPU cores.
SearchOption.AllDirectories
From the docs: ''...follows symbolic links...', which is
microsoft-ese for 'follows shortcuts'.
IOW, when it finds a shortcut to a folder that was
already processed in a child of that folder, it will
process the parent folder again.
IOW, this option is dangerous because it can lead
to infinite recursion.
First Time I've read that Tony ... and the SearchOption.AllDirectories has been around for a while ... surprised it's not plastered all over the web.
-
Excellent Thread!
Thanks guys.
-
Couldn't you just use ' DirectoryInfo.GetFiles ' and have the search option set to ' AllDirectories '? Untested, but I have this in my batch plot program, learned from Glenn, and it works with a filter for ' *.dwg '.
MSDN page for DirectoryInfo.GetFiles
[ http://msdn.microsoft.com/en-us/library/ms143327.aspx ]
-
Couldn't you just use ' DirectoryInfo.GetFiles ' and have the search option set to ' AllDirectories '? Untested, but I have this in my batch plot program, learned from Glenn, and it works with a filter for ' *.dwg '.
MSDN page for DirectoryInfo.GetFiles
[ http://msdn.microsoft.com/en-us/library/ms143327.aspx ]
Yes you can, but as mentioned on the page at the link I posted,
the entire operation fails if you don't have sufficient access rights
(as rare as that may be) for every sub directory.
If you traverse the folder tree manually, you can handle the security
exceptions that are thrown if you don't have sufficient rights for a
given folder, log the error or do whatever else you want to do, and
continue processing folders, without the entire operation failing.
-
Couldn't you just use ' DirectoryInfo.GetFiles ' and have the search option set to ' AllDirectories '? Untested, but I have this in my batch plot program, learned from Glenn, and it works with a filter for ' *.dwg '.
MSDN page for DirectoryInfo.GetFiles
[ http://msdn.microsoft.com/en-us/library/ms143327.aspx ]
Yes you can, but as mentioned on the page at the link I posted,
the entire operation fails if you don't have sufficient access rights
(as rare as that may be) for every sub directory.
If you traverse the folder tree manually, you can handle the security
exceptions that are thrown if you don't have sufficient rights for a
given folder, log the error or do whatever else you want to do, and
continue processing folders, without the entire operation failing.
Thanks Tony. When I get a chance I'll go and read the pages you linked to.
-
And if you are only searching for files based on a pattern, it may not
matter if you have access rights, so AllDirectories may work in any
case. In my own file search class, I can do more specialized searches
that involve accessing each file (e.g., modified after a certain date,
or what have you), which means that my code must have the needed
access rights.
Couldn't you just use ' DirectoryInfo.GetFiles ' and have the search option set to ' AllDirectories '? Untested, but I have this in my batch plot program, learned from Glenn, and it works with a filter for ' *.dwg '.
MSDN page for DirectoryInfo.GetFiles
[ http://msdn.microsoft.com/en-us/library/ms143327.aspx ]
Yes you can, but as mentioned on the page at the link I posted,
the entire operation fails if you don't have sufficient access rights
(as rare as that may be) for every sub directory.
If you traverse the folder tree manually, you can handle the security
exceptions that are thrown if you don't have sufficient rights for a
given folder, log the error or do whatever else you want to do, and
continue processing folders, without the entire operation failing.
Thanks Tony. When I get a chance I'll go and read the pages you linked to.
-
Hi,
I know this is an old topic, but while I'm trying to have a look around F#, I thaught it was a good exercice.
A 'try ... with' ( as C# 'try ... catch') statements used to ignore the limited access folders
let FindFiles folder pattern =
let lst = ref List.Empty
let rec foo dir pat =
for f in Directory.GetFiles(dir, pat) do lst := f :: !lst
for d in Directory.GetDirectories(dir) do
try foo d pat with | ex -> ignore()
foo folder pattern
List.toArray(List.rev(!lst))
-
Hi,
I know this is an old topic, but while I'm trying to have a look around F#, I thaught it was a good exercice.
A 'try ... with' ( as C# 'try ... catch') statements used to ignore the limited access folders
let FindFiles folder pattern =
let lst = ref List.Empty
let rec foo dir pat =
for f in Directory.GetFiles(dir, pat) do lst := f :: !lst
for d in Directory.GetDirectories(dir) do
try foo d pat with | ex -> ignore()
foo folder pattern
List.toArray(List.rev(!lst))
Hi Gile,
welcome to the club! (Cue J.H.Marx: "I don’t care to belong to any club that will have me as a member.")
The canonical example of recursive directory search is of course here: http://www.expert-fsharp.com/CodeSamples/Chapter03/Example08/script.fsx (http://www.expert-fsharp.com/CodeSamples/Chapter03/Example08/script.fsx), from Expert F# by Don Syme, Adam Granicz and Antonio Cisternino.
Modifying that with the requirement to ignore dirs with insufficient permission and to return an array yields:
let FindFiles folder pat =
let rec foo dir =
try
Directory.GetDirectories dir |> Array.collect foo
|> Array.append (Directory.GetFiles(dir, pat))
with _ -> Array.empty
foo folder
Have lots of fun! Thorsten
-
Thank you very much kaefer :-o
-
Hi,
It seems there's no need to use a sub function:
let rec FindFiles dir pat =
try
Directory.GetDirectories dir
|> Array.collect (fun x -> FindFiles x pat)
|> Array.append (Directory.GetFiles (dir, pat))
with _ -> Array.empty
-
It seems there's no need to use a sub function:
let rec FindFiles dir pat =
try
Directory.GetDirectories dir
|> Array.collect (fun x -> FindFiles x pat)
|> Array.append (Directory.GetFiles (dir, pat))
with _ -> Array.empty
Oh, dear. Get ready for the next level:
let rec FindFiles dir pat =
try [| yield! Directory.GetFiles (dir, pat)
for x in Directory.GetDirectories dir do yield! FindFiles x pat |]
with _ -> Array.empty