Author Topic: Findfile recursive ..  (Read 11504 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Findfile recursive ..
« 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.



First try a findfile with the qualified Path

Then some recursion variations ..

Code: [Select]
        [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 ..

Quote
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


kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #1 on: December 19, 2008, 09:38:39 PM »
I 'spose I could try a LINQ Query as well ....  :|
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8704
  • AKA Daniel
Re: Findfile recursive ..
« Reply #2 on: December 19, 2008, 09:51:06 PM »
Nice work Kerry!  8-)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #3 on: December 19, 2008, 09:54:29 PM »

Thanks Dan.

Holidays are great .. plenty of research and play time :)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

TonyT

  • Guest
Re: Findfile recursive ..
« Reply #4 on: December 20, 2008, 11:52:38 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.


Assuming you actually wanted a non-recursive version,
I suppose that works.

Otherwise, this (which I've been using for ages) can do it:

Code: [Select]

/// 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 );
   }
}


It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8704
  • AKA Daniel
Re: Findfile recursive ..
« Reply #5 on: December 21, 2008, 12:08:34 AM »
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:

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #6 on: December 21, 2008, 12:12:22 AM »

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" );


kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

TonyT

  • Guest
Re: Findfile recursive ..
« Reply #7 on: December 21, 2008, 02:55:42 AM »
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.

« Last Edit: December 21, 2008, 03:06:26 AM by TonyT »

uncoolperson

  • Guest
Re: Findfile recursive ..
« Reply #8 on: December 21, 2008, 12:11:08 PM »
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

Quote
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)
« Last Edit: December 21, 2008, 12:18:04 PM by uncoolperson »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #9 on: December 21, 2008, 10:00:46 PM »
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");


Quote
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
 
« Last Edit: December 21, 2008, 10:05:15 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8704
  • AKA Daniel
Re: Findfile recursive ..
« Reply #10 on: December 21, 2008, 10:03:31 PM »
Alphabet Soup.dwg  :laugh:

pkohut

  • Guest
Re: Findfile recursive ..
« Reply #11 on: December 21, 2008, 10:44:57 PM »
and, because it's Monday and I'm home ....

Monday? What UTM are you in?  10T for me.

Paul

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #12 on: December 21, 2008, 11:00:34 PM »
Gender:   yes
Age:         Mesozoic
Location:     Brisbane, Australia [ gmt +10 ]
Local Time: 2008-12-21, 14:00:45
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

pkohut

  • Guest
Re: Findfile recursive ..
« Reply #13 on: December 21, 2008, 11:12:46 PM »
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

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #14 on: December 21, 2008, 11:17:03 PM »
ok .. UTM is 56J
« Last Edit: December 21, 2008, 11:20:04 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8704
  • AKA Daniel
Re: Findfile recursive ..
« Reply #15 on: December 21, 2008, 11:24:53 PM »
I’m in 17T but will be in 51R in February.

It's too cold in 17T   :lol:

TonyT

  • Guest
Re: Findfile recursive ..
« Reply #16 on: December 21, 2008, 11:25:27 PM »
Quote

   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.


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #17 on: December 21, 2008, 11:27:29 PM »
Dan,
that  sounds like really bad poetry lyrics
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8704
  • AKA Daniel
Re: Findfile recursive ..
« Reply #18 on: December 21, 2008, 11:38:46 PM »
WooahYa I’m down and out in 17T where the wind chill is -17°C   :laugh:

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Findfile recursive ..
« Reply #19 on: December 21, 2008, 11:42:41 PM »
Quote

   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.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

TonyT

  • Guest
Re: Findfile recursive ..
« Reply #20 on: December 22, 2008, 05:29:17 AM »
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.

Quote

   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.
« Last Edit: December 22, 2008, 06:06:41 AM by TonyT »

Draftek

  • Guest
Re: Findfile recursive ..
« Reply #21 on: December 22, 2008, 07:52:11 AM »
Excellent Thread!
Thanks guys.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Findfile recursive ..
« Reply #22 on: December 22, 2008, 03:29:34 PM »
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 ]
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

TonyT

  • Guest
Re: Findfile recursive ..
« Reply #23 on: December 23, 2008, 09:27:04 AM »
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.


T.Willey

  • Needs a day job
  • Posts: 5251
Re: Findfile recursive ..
« Reply #24 on: December 23, 2008, 11:01:05 AM »
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.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

TonyT

  • Guest
Re: Findfile recursive ..
« Reply #25 on: December 23, 2008, 11:56:56 AM »
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.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Findfile recursive ..
« Reply #26 on: November 10, 2010, 05:53:50 PM »
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

Code: [Select]
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))
Speaking English as a French Frog

kaefer

  • Guest
Re: Findfile recursive ..
« Reply #27 on: November 11, 2010, 04:21:54 AM »
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

Code: [Select]
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, 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:
Code: [Select]
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

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Findfile recursive ..
« Reply #28 on: November 11, 2010, 05:17:45 AM »
Thank you very much kaefer :-o
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Findfile recursive ..
« Reply #29 on: November 12, 2010, 02:41:15 AM »
Hi,

It seems there's no need to use a sub function:
Code: [Select]
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
Speaking English as a French Frog

kaefer

  • Guest
Re: Findfile recursive ..
« Reply #30 on: November 12, 2010, 07:13:56 AM »
It seems there's no need to use a sub function:
Code: [Select]
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:
Code: [Select]
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