Author Topic: trying to traverse subdirectories  (Read 8271 times)

cgsna@yahoo.com

  • Community Member
  • Posts: 13
  • Hero Points: 0
trying to traverse subdirectories
« on: January 13, 2007, 04:15:21 am »
Greetings all,

Ok, here is what I am trying to do.  I need a Slick-C macro (for Windoze) to take a starting path specified as an argument, traverse it and all of its subdirectories, and open a window/buffer for each file with the file extension also specified as an argument.  However, at this point, the file type is irrelevant.  I thought it would be an easy task, but not so.  As far as opening the window/buffer once a file is found, I don't have a problem; traversing the subdirectories is a different story.  The following excerpted lines of code illustrate the problem that I am having.

#include "slick.sh"

defmain()

   parse arg(1) with StartPath .;

   _str temp = StartPath :+ '\*.* +D +P';
   _str filename = file_match(temp,1);
     
   while(filename != '') 
   {
      _str attrs = file_list_field(filename, DIR_ATTR_COL, DIR_ATTR_WIDTH);
      messageNwait('name found='filename);     
      filename= file_match(' +d -p 'filename,0);
   }
   messageNwait('done');
 }

When I comment out the _str attrs = line, it lists every file in the directory, as I would expect, including the subdirectories.  With that line in place, however, it lists the file c:\StartDir\.\ only, and then immediately goes to 'done'.  Any ideas?

Thanks,
Clark



Graeme

  • Senior Community Member
  • Posts: 2387
  • Hero Points: 314
Re: trying to traverse subdirectories
« Reply #1 on: January 13, 2007, 04:44:48 am »
The problem is that file_list_field also calls file_match

Code: [Select]
  _str line=file_match('-p +VRHSD 'maybe_quote_filename(filename),1);

Whilst the slick help doesn't explicitly say so, having done a "find first" you have to do all the "find nexts" without doing another "find first".  On windows, these use the api calls FindFirstFile (which returns a serach handle) and FindNextFile, which is passed the search handle returned by FindFirstFile.

Hence file_list_field is doing a "find first" and destroying the search handle created by your own find first.
BTW - you might want to use maybe_quote_filename in your own code if you think there could be spaces in your path.

Graeme

cgsna@yahoo.com

  • Community Member
  • Posts: 13
  • Hero Points: 0
Re: trying to traverse subdirectories
« Reply #2 on: January 13, 2007, 05:30:17 am »
Well then, that seems messed-up.  If file_list_field does a file_match, obviously as a find first, then how can it be used it in a loop on a whole direcectory of files? 

Graeme

  • Senior Community Member
  • Posts: 2387
  • Hero Points: 314
Re: trying to traverse subdirectories
« Reply #3 on: January 13, 2007, 06:37:00 am »
Since there isn't any info in the help about how it's implemented in slick, I can only guess, but with Windows, if you're iterating through folders, when you come to a new directory, you use FindFirstFile on the new directory and get a new search handle, before you've finished iterating through the parent folder - so you actually have a stack of search handles.  Most likely slick will have a stack of search handles as well - but I don't know what other operating systems do.  Slick might even use boost file system code.

Hence I don't know how slick uses the 'filename' string when you do a find next because on Windows, the search handle is enough to get you the next file (in the same folder).

You might be able to do it by adding the +V option to your own calls to file_match and then use strip() as file_list_field does but the help says +V doesn't return any path info but you'll need the path info if a directory name has been returned because slick *might* use the filename you give it to determine when to start searching a new folder.

The other (and better) way is to build a big array of the filenames returned by file_match and re-iterate through them after doing all the file_match calls.

Graeme

cgsna@yahoo.com

  • Community Member
  • Posts: 13
  • Hero Points: 0
Re: trying to traverse subdirectories
« Reply #4 on: January 14, 2007, 01:08:19 am »
Graeme, first off, I want you to know that I really appreciate your help.

Ok, I am making progress with my undertaking.  I found a nifty little routine called dir_match() which searches for directory entries, and similar to file_match() operates on a Find First/First Next basis.  However, I have noticed that in a Find Next situation, it does not seem to really care what you put for "name", and therefore must be using some Slick-stored file handle that the user has no direct access to.  So, that brings up this question.  Once I have exhausted all Find Nexts for the current handle, how do I dispose of the current handle, and start doing Find Nexts on the previous handle?  It does not seem to go there by itself.  Know what I mean?

Thanks,
Clark

Graeme

  • Senior Community Member
  • Posts: 2387
  • Hero Points: 314
Re: trying to traverse subdirectories
« Reply #5 on: January 14, 2007, 08:57:00 am »
Quote
So, that brings up this question.  Once I have exhausted all Find Nexts for the current handle, how do I dispose of the current handle, and start doing Find Nexts on the previous handle?  It does not seem to go there by itself.  Know what I mean?

I think I didn't think hard enough.  I assumed from your first post where you said your code successfully traversed subdirectories as well as the parent directory that Slick was handling the recursion automatically.  From looking at the code in CheckForUserInstalledJava, where it does a string of find-firsts and no find-nexts (actually same goes for file_list_field now that I think about it), that each find-first destroys any existing search handle.  If it didn't, the system would grind to a halt when the supply of handles was exhausted.

I guess this means you have to handle the recursion yourself and step through the entire folder first before recursing i.e. you have to save the directory names in a list and recurse them when you get to the end of the current folder.  You could either use a recursive function or probably you can just build up an ever increasing array of directory names and work your way down it.  It's important to remember that you have to do find-next on the entire directory before doing another find-first.  You should be able to have the +V switch in all the calls to file_match  - Slick help certainly indicates this should work (I should have realised this before).

Graeme

Graeme

  • Senior Community Member
  • Posts: 2387
  • Hero Points: 314
Re: trying to traverse subdirectories
« Reply #6 on: January 14, 2007, 09:28:22 am »

Well I decided to try this myself.  I found that Slick does automatically do the folder recursion for you if you use the +T switch.  If you use the +V switch, you can't use the string that slick returns in the next call to file_match because it has lots of junk in it.  Dunno how you can then combine automatic recursion with the +v switch.

By the way, in case you didn't know, "say" is a useful thing for outputting debug info.

Code: [Select]
_command void fmtest() name_info(',')
{
   _str temp = 'c:\somepath\*.*" +d +t';
   _str filename = file_match(temp,1);
   while(filename != '')
   {
      say('name found='filename);     
      filename= file_match(filename,0);
   }
}

Graeme

cgsna@yahoo.com

  • Community Member
  • Posts: 13
  • Hero Points: 0
Re: trying to traverse subdirectories
« Reply #7 on: January 16, 2007, 01:55:53 am »
Graeme,

I think my problems are solved.  Thanks again for all your help.  +t made all the difference in the world.  I don't even need to use dir_match anymore.

Best regards,
Clark