Q:  I need to process certain files (*.ssd) in a user selected directory and every nested directory thereafter using Delphi. Anyone has any pointers to give me?  What calls to use (my main concern is how to recognize a subdirectory while scanning a directory), may be a fragment of code that does something similar?

A:  FindFirst and FindNext are the key functions.

Here is the short version.  It is written in a generic way so that you can use the FileFind() procedure from any unit.

unit Findfile;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Edit2: TEdit;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure FileFind(StartingDirectory, FileName: string; FilesFound: TStringList);

  procedure SearchTree;
  var
    SearchRec: TSearchRec;
    DosError: integer;
    dir: string;
  begin
    GetDir(0, dir);
    if dir[length(dir)] <> '\' then dir := dir + '\';
    DosError := FindFirst(FileName, 0, SearchRec);
    while DosError = 0 do begin
      try
        FilesFound.add(dir + SearchRec.name);
      except
        on EOutOfResources do begin
          ShowMessage('Too many files.');
          abort;
        end;
      end;
      DosError := FindNext(SearchRec);
    end;
    {Now that we have all the files we need, lets go to a subdirectory.}
    DosError := FindFirst('*.*', faDirectory, SearchRec);
    while DosError = 0 do begin
      {If there is one, go there and search.}
      if ((SearchRec.attr and faDirectory = faDirectory) and
        (SearchRec.name <> '.') and (SearchRec.name <> '..')) then begin
        ChDir(SearchRec.name);
        SearchTree; {Time for the recursion!}
        ChDir('..'); {Down one level.}
      end;
      DosError := FindNext(SearchRec); {Look for another subdirectory}
    end;
  end; {SearchTree}

begin
  FilesFound.clear;
  ChDir(StartingDirectory);
  SearchTree;
end; {FileFind}

procedure TForm1.Button1Click(Sender: TObject);
var
  t: TStringList;
begin
  t := TStringList.create;
  FileFind(edit2.text, edit1.text, t);
  listbox1.items.assign(t);
  t.free;
end;

end.
 

Here is an example using a slightly different format:

unit Dirlist1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    Function LogFiles( Const path: String; Const SRec: TSearchRec ): Boolean;
    { Private-Declaration }
  public
    { Public-Declaration }
  end;

var
  Form1: TForm1;

implementation

Type
  TLogFunct = Function( Const path: String; Const SRec: TSearchRec ): Boolean
                of Object;
{$R *.DFM}

Procedure FindRecursive( Const path: String; Const mask: String;
                         LogFunction: TLogFunct );
  Var
    fullpath: String;
  Function Recurse( Var path: String; Const mask: String ): Boolean;
    Var
      SRec: TSearchRec;
      retval: Integer;
      oldlen: Integer;
    Begin
      Recurse := True;
      oldlen := Length( path );
      (* phase 1, look for normal files *)
      retval := FindFirst( path+mask, faAnyFile, SRec );
      While retval = 0 Do Begin
        If (SRec.Attr and (faDirectory or faVolumeID)) = 0 Then
          (* we found a file, not a directory or volume label,
             log it. Bail out if the log function returns false. *)
          If not LogFunction( path, SRec ) Then Begin
            Result := False;
            Break;
          End;
        retval := FindNext( SRec );
      End;
      FindClose( SRec );
      If not Result Then Exit;

      (* Phase II, look for subdirectories and recurse thru them *)
      retval := FindFirst( path+'*.*', faDirectory, SRec );
      While retval = 0 Do Begin
        If (SRec.Attr and faDirectory) <> 0 Then (* we have a directory *)
          If (SRec.Name <> '.') and (SRec.Name <> '..') Then Begin
            path := path + SRec.Name + '\';
            If not Recurse( path, mask ) Then Begin
              Result := False;
              Break;
            End;
            Delete( path, oldlen+1, 255 );
          End;
        retval := FindNext( SRec );
      End;
      FindClose( SRec );
    End;
  Begin
    If path = '' Then
      GetDir(0, fullpath)
    Else
      fullpath := path;
    If fullpath[Length(fullpath)] <> '\' Then
      fullpath := fullpath + '\';
    If mask = '' Then
      Recurse( fullpath, '*.*' )
    Else
      Recurse( fullpath, mask );
  End;
 

Function TForm1.LogFiles( Const path: String; Const SRec: TSearchRec ): Boolean;
  Begin
    Listbox1.Items.Add( path+SRec.Name );
    Result := True;   (* proceeed with recursion *)
  End;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Application.Terminate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ListBox1.Clear;
  Listbox1.Perform( WM_SETREDRAW, 0, 0 );
  FindRecursive( Edit1.Text, Edit2.Text, LogFiles );
  Listbox1.Perform( WM_SETREDRAW, 1, 0 );
  Listbox1.Refresh;
end;

end.

---- dirlist1.dfm -----

object Form1: TForm1
  Left = 260
  Top = 222
  Width = 642
  Height = 300
  Caption = 'Recursive Directory Scan'
  Font.Color = clWindowText
  Font.Height = -17
  Font.Name = 'System'
  Font.Style = []
  PixelsPerInch = 120
  Position = poScreenCenter
  TextHeight = 20
  object Label1: TLabel
    Left = 480
    Top = 24
    Width = 116
    Height = 20
    Caption = '&Path to search'
    FocusControl = Edit1
  end
  object Label2: TLabel
    Left = 480
    Top = 96
    Width = 74
    Height = 20
    Caption = '&File Mask'
    FocusControl = Edit2
  end
  object ListBox1: TListBox
    Left = 16
    Top = 24
    Width = 449
    Height = 225
    ItemHeight = 20
    TabOrder = 0
  end
  object Edit1: TEdit
    Left = 480
    Top = 48
    Width = 137
    Height = 29
    TabOrder = 1
  end
  object Edit2: TEdit
    Left = 480
    Top = 120
    Width = 137
    Height = 29
    TabOrder = 2
  end
  object Button1: TButton
    Left = 480
    Top = 168
    Width = 137
    Height = 33
    Caption = '&Search'
    Default = True
    TabOrder = 3
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 480
    Top = 216
    Width = 137
    Height = 33
    Caption = 'Close'
    TabOrder = 4
    OnClick = Button2Click
  end
end