Board index » delphi » Must it be "Brute Force"?

Must it be "Brute Force"?

   I am trying to gather the file information about certain files on the
A drive.  They may exist on different subdirectories, and I'd like to
identify the files I find with their full paths (A:\filename,
A:\subdir1\filename, a:\subdir2\filename, etc.).  I am able to _find_ all
the files (using a recursive Find* routine I found here last month), but
Find* only returns the filename and no more.  This routine constructs and
lists the full path, but I'd like to be able to store and sort the full
pathnames before I display the ones I find.
   It appears that I must "construct" a string with all the information I
want and store that in an array for sorting/listing.  I'd like to avoid
this, if possible, because I could have (up to) 200+ such files (and data
lines), and I'm concerned about the amount of Stack I'd have to use to do
all this.  No, I won't build a Linked List (and sort that), which I'd
have to explicitly dispose of when this process is completed - I want to
do it all in a subprogram and keep the data on the Stack.
   Given these requirements, is there a better way to collect, sort, and
make available (up to) 200+ full paths which are recursively found?
   Following is the routine I've used to start building this process:

procedure Recurser;
procedure ListAll (Root : String);
var SR : SearchRec;
     D : DirStr;
     N : NameStr;
     E : ExtStr;
begin
  Root := FExpand (Root); FindFirst (Root, AnyFile, SR);
  FSplit (Root,D,N,E);
  while DOSError = 0 do with SR do
    begin
      if ((Attr and Directory) = Directory) and (Name <> '.') and
         (Name <> '..') then
        begin
          writeln (D,Name); ListAll (D+Name+'\*.*')
        end
      else writeln (D+Name);
      Findnext (SR)
    end;
end;
begin
  ListAll ('A:\*.*')
end;

 

Re:Must it be "Brute Force"?


Quote
Mike Copeland wrote:

>    I am trying to gather the file information about certain files on the
> A drive.  They may exist on different subdirectories, and I'd like to
> identify the files I find with their full paths (A:\filename,
> A:\subdir1\filename, a:\subdir2\filename, etc.).  I am able to _find_ all
> the files (using a recursive Find* routine I found here last month), but
> Find* only returns the filename and no more.  This routine constructs and
> lists the full path, but I'd like to be able to store and sort the full
> pathnames before I display the ones I find.
>    It appears that I must "construct" a string with all the information I
> want and store that in an array for sorting/listing.  I'd like to avoid
> this, if possible, because I could have (up to) 200+ such files (and data
> lines), and I'm concerned about the amount of Stack I'd have to use to do
> all this.  No, I won't build a Linked List (and sort that), which I'd
> have to explicitly dispose of when this process is completed - I want to
> do it all in a subprogram and keep the data on the Stack.
>    Given these requirements, is there a better way to collect, sort, and
> make available (up to) 200+ full paths which are recursively found?
>    Following is the routine I've used to start building this process:

> procedure Recurser;
> procedure ListAll (Root : String);
> var SR : SearchRec;
>      D : DirStr;
>      N : NameStr;
>      E : ExtStr;
> begin
>   Root := FExpand (Root); FindFirst (Root, AnyFile, SR);
>   FSplit (Root,D,N,E);
>   while DOSError = 0 do with SR do
>     begin
>       if ((Attr and Directory) = Directory) and (Name <> '.') and
>          (Name <> '..') then
>         begin
>           writeln (D,Name); ListAll (D+Name+'\*.*')
>         end
>       else writeln (D+Name);
>       Findnext (SR)
>     end;
> end;
> begin
>   ListAll ('A:\*.*')
> end;

Please see an undocumented interrupt that returns the full path of
one file name .

I can't shell out to dos to grep actually but i 'm sure you will find it
in any interrupt list available or in swags

didier

Re:Must it be "Brute Force"?


Quote
Mike Copeland wrote:
>    I am trying to gather the file information about certain files on the
> A drive.  They may exist on different subdirectories, and I'd like to
> identify the files I find with their full paths (A:\filename,
> A:\subdir1\filename, a:\subdir2\filename, etc.).  I am able to _find_ all
> the files (using a recursive Find* routine I found here last month), but
> Find* only returns the filename and no more.  This routine constructs and
> lists the full path, but I'd like to be able to store and sort the full
> pathnames before I display the ones I find.
>    It appears that I must "construct" a string with all the information I
> want and store that in an array for sorting/listing.  I'd like to avoid
> this, if possible, because I could have (up to) 200+ such files (and data
> lines), and I'm concerned about the amount of Stack I'd have to use to do
> all this.  No, I won't build a Linked List (and sort that), which I'd
> have to explicitly dispose of when this process is completed - I want to
> do it all in a subprogram and keep the data on the Stack.

If I understand correctly, You want the full path to be stored, but you
don't want the overhead of storing that full path?  One way I can think
of is to enumerate each directory as you find it, then store the just
the filename from each directory with the value referring to the
directory it's in.  It may not solve the problems, but it can reduce
memory requirements, especially when directory names start getting
long.  No matter what though, it's still going to be a tough job trying
to squeeze it in so it all fits in the stack segment.  (Isn't that what
dynamic allocation is for in the first place?)

- Show quoted text -

Quote
>    Given these requirements, is there a better way to collect, sort, and
> make available (up to) 200+ full paths which are recursively found?
>    Following is the routine I've used to start building this process:

> procedure Recurser;
> procedure ListAll (Root : String);
> var SR : SearchRec;
>      D : DirStr;
>      N : NameStr;
>      E : ExtStr;
> begin
>   Root := FExpand (Root); FindFirst (Root, AnyFile, SR);
>   FSplit (Root,D,N,E);
>   while DOSError = 0 do with SR do
>     begin
>       if ((Attr and Directory) = Directory) and (Name <> '.') and
>          (Name <> '..') then
>         begin
>           writeln (D,Name); ListAll (D+Name+'\*.*')
>         end
>       else writeln (D+Name);
>       Findnext (SR)
>     end;
> end;
> begin
>   ListAll ('A:\*.*')
> end;

--
Scott Earnest        | We now return you to our regularly |
set...@ix.netcom.com | scheduled chaos and mayhem. . . .  |

Re:Must it be "Brute Force"?


Quote
> >    I am trying to gather the file information about certain files on the
> > A drive.  They may exist on different subdirectories, and I'd like to
> > identify the files I find with their full paths (A:\filename,
> > A:\subdir1\filename, a:\subdir2\filename, etc.).  I am able to _find_ all
> > the files (using a recursive Find* routine I found here last month), but
> > Find* only returns the filename and no more.  This routine constructs and
> > lists the full path, but I'd like to be able to store and sort the full
> > pathnames before I display the ones I find.
> >    It appears that I must "construct" a string with all the information I
> > want and store that in an array for sorting/listing.  I'd like to avoid
> > this, if possible, because I could have (up to) 200+ such files (and data
> > lines), and I'm concerned about the amount of Stack I'd have to use to do
> > all this.  No, I won't build a Linked List (and sort that), which I'd
> > have to explicitly dispose of when this process is completed - I want to
> > do it all in a subprogram and keep the data on the Stack.

> If I understand correctly, You want the full path to be stored, but you
> don't want the overhead of storing that full path?  One way I can think
> of is to enumerate each directory as you find it, then store the just
> the filename from each directory with the value referring to the
> directory it's in.  It may not solve the problems, but it can reduce
> memory requirements, especially when directory names start getting
> long.  

   Yes, that's the basic <g> problem, and you've verified my supposition.
I may have to do what you suggest, if Stack becomes the problem I fear it
might...

Quote
>No matter what though, it's still going to be a tough job trying
> to squeeze it in so it all fits in the stack segment.  (Isn't that what
> dynamic allocation is for in the first place?)

   Yes, but I haven't got very much of that - less than Stack, ftm.  This
is my largest application, already overlayed to the hilt, and I sometimes
have as little as 2000 bytes of Heap available when all the data is
stored - this above process I've outlined is an occasional "utility"
function I sometimes must execute within the application (so I want it to
be as unintrusive as possible...).
   Thanks, Scott.

Re:Must it be "Brute Force"?


In article <MPG.e90eb93b4976e33989...@news.primenet.com> of Mon, 22 Sep
1997 20:56:01 in comp.lang.pascal.borland, Mike Copeland

Quote
<mrc...@primenet.com> wrote:

   I am trying to gather the file information about certain files on the
A drive. ....

Comparing your code with my URL:
        http://www.merlyn.demon.co.uk/programs/listdirs.pas
 - good example IMHO of how two programmers produce *similar* code for
the same job.

I think you should use a list or tree structure, but so be it.  Actually
you will be using a sort of linked list of recursing stack frames.

IMHO you don't need to sort the *full* pathnames; you can contrive to
discover the names in a nearly-sorted order.   (I *assume* an
alphabetical sort on full pathname is required.)

You *seem* to be saying that you'll have to sort an array containing
strings such as 'a:\d1\d2\d3\file' - ISTM that you can reduce the amount
of sorting (remember o(n log n)) and the size of the items compared and
sorted as follows; I describe a mid-stage of the recursion.

Do FindFirst/FindNext, storing the Name and Attribute fields in an array.
Sort this array, keyed on Dir-field of Attr then Name; you may want D to
sort high or low.  Then scan this array, recursing into directories and
listing files.  When recursing, pass in as a parameter the path-so-far,
for prepending to name for printing... you almost do anyway, and the
"\*.*" you add twice in the calls of ListAll could be added once in the
body.

This will use less stack, as only a single copy of each directory's name
is stored.

To avoid lots of little arrays, each of which has to be ample as it's
declared before you know what is wanted, declare a biggish global array
and use the remainder of it where I say "array" above.  Now, you *could*
pass in not the name so far, but a list (or string) of indexes to names.

Hopefully, you've not got to worry about long file names.

HTH.

--
John Stockton, Surrey, UK.    j...@merlyn.demon.co.uk    Turnpike v1.12    MIME.
  Web URL: http://www.merlyn.demon.co.uk/ -- includes FAQqish topics and links.
  Correct 4-line sig separator is as above, a line comprising "-- " (SoRFC1036)
  Before a reply, quote with ">" / "> ", known to good news readers (SoRFC1036)

Re:Must it be "Brute Force"?


Quote
Mike Copeland wrote:
>    I am trying to gather the file information about certain files on the
> A drive.  They may exist on different subdirectories, and I'd like to
> identify the files I find with their full paths (A:\filename,
> A:\subdir1\filename, a:\subdir2\filename, etc.).  I am able to _find_ all
> the files (using a recursive Find* routine I found here last month), but
> Find* only returns the filename and no more.  This routine constructs and
> lists the full path, but I'd like to be able to store and sort the full
> pathnames before I display the ones I find.
>    It appears that I must "construct" a string with all the information I
> want and store that in an array for sorting/listing.  I'd like to avoid
> this, if possible, because I could have (up to) 200+ such files (and data
> lines), and I'm concerned about the amount of Stack I'd have to use to do
> all this.  No, I won't build a Linked List (and sort that), which I'd
> have to explicitly dispose of when this process is completed - I want to
> do it all in a subprogram and keep the data on the Stack.

Even I don't  understand how you gonna do that (build your listcompletely on
stack), I'de not advise to do so. Even when pure
filenames stored it could become size problem when you scan a root
or a hard disk. Directory structure is a tree, and a tree is
an optimal way to keep it in memory. But it also depends
what sorting problems you have. If you have to sort filenames
within each [sub]directory, then tree structure is good for it.
My suggestion: have a global object tree or pass a local
object to your recursive procedure as 'var'.Also pass the current
node to add. After sorting and printing out you must
surely free all the nodes explicitly. But is that a real problem??

- Show quoted text -

Quote
>    Given these requirements, is there a better way to collect, sort, and
> make available (up to) 200+ full paths which are recursively found?
>    Following is the routine I've used to start building this process:

> procedure Recurser;
> procedure ListAll (Root : String);
> var SR : SearchRec;
>      D : DirStr;
>      N : NameStr;
>      E : ExtStr;
> begin
>   Root := FExpand (Root); FindFirst (Root, AnyFile, SR);
>   FSplit (Root,D,N,E);
>   while DOSError = 0 do with SR do
>     begin
>       if ((Attr and Directory) = Directory) and (Name <> '.') and
>          (Name <> '..') then
>         begin
>           writeln (D,Name); ListAll (D+Name+'\*.*')
>         end
>       else writeln (D+Name);
>       Findnext (SR)
>     end;
> end;
> begin
>   ListAll ('A:\*.*')
> end;

Re:Must it be "Brute Force"?


In article <MPG.e917887176108e3989...@news.primenet.com>,
mrc...@primenet.com says...

Quote

>>                            ...it's still going to be a tough job trying
>> to squeeze it in so it all fits in the stack segment.  (Isn't that what
>> dynamic allocation is for in the first place?)

>   Yes, but I haven't got very much of that - less than Stack, ftm.  This
>is my largest application, already overlayed to the hilt, and I sometimes
>have as little as 2000 bytes of Heap available when all the data is
>stored...

If there's no room in the data segment and not enough in the heap and
not enough on the stack.... you might do it on disk.  Slow, of course,
but roomy.

--
R. N. (dick) Wisan  - Email: wis...@norwich.net
                    - Snail: 37 Clinton Street, Oneonta NY 13820, U.S.A.
                    - Just your opinion, please, ma'am: No fax.

Re:Must it be "Brute Force"?


Il giorno 22 Sep 1997 20:56:01 -0700, mrc...@primenet.com (Mike
Copeland) dal profondo del suo sub-cosciente ha scritto :

Quote
>   I am trying to gather the file information about certain files on the
>A drive.  They may exist on different subdirectories, and I'd like to
>identify the files I find with their full paths (A:\filename,
>A:\subdir1\filename, a:\subdir2\filename, etc.).  I am able to _find_ all
>the files (using a recursive Find* routine I found here last month), but
>Find* only returns the filename and no more.
>  This routine constructs and
>lists the full path, but I'd like to be able to store and sort the full
>pathnames before I display the ones I find.
>   It appears that I must "construct" a string with all the information I
>want and store that in an array for sorting/listing.  I'd like to avoid
>this, if possible, because I could have (up to) 200+ such files (and data
>lines), and I'm concerned about the amount of Stack I'd have to use to do
>all this.  No, I won't build a Linked List (and sort that), which I'd
>have to explicitly dispose of when this process is completed - I want to
>do it all in a subprogram and keep the data on the Stack.
>   Given these requirements, is there a better way to collect, sort, and
>make available (up to) 200+ full paths which are recursively found?
>   Following is the routine I've used to start building this process:

I think that you cannot mantain all these information onto the stack.
I also think you have not to build "strings" to mantain informations
about the files.
For example for each file found you can save the SR corresponding
record.
You can build a binary tree in which you insert the items and so you
will sort them automatically.

Keep in mind that in the following code you should replace Root :
String with Root : DirStr defining DirStr : char[64];
reducing the amount of memory consumed.

(Name <> '.') and (Name <> '..') can be replaced with (Name[1]<>'.')

Bye
use binary tree and you will have no problems.
Andrea

- Show quoted text -

Quote
>procedure Recurser;
>procedure ListAll (Root : String);
>var SR : SearchRec;
>     D : DirStr;
>     N : NameStr;
>     E : ExtStr;
>begin
>  Root := FExpand (Root); FindFirst (Root, AnyFile, SR);
>  FSplit (Root,D,N,E);
>  while DOSError = 0 do with SR do
>    begin
>      if ((Attr and Directory) = Directory) and (Name <> '.') and
>         (Name <> '..') then
>        begin
>          writeln (D,Name); ListAll (D+Name+'\*.*')
>        end
>      else writeln (D+Name);
>      Findnext (SR)
>    end;
>end;
>begin
>  ListAll ('A:\*.*')
>end;

Andrea Laforgia
--------------------------------------------------------
Tutto cio' che ho scritto sul rigo seguente e' falso
Tutto cio' che ho scritto sul rigo precedente e' falso
--------------------------------------------------------
"Grattatio pallarum omnia mala fugit" (Andrea Laforgia)
--------------------------------------------------------

Other Threads