Solved

Search/Replace

Posted on 2004-03-25
10
302 Views
Last Modified: 2010-04-05
Dear friends,

My question is older than running...
I would need your help for writing a script for searching and replace a phrase,
for example, in all files .txt in all disks available on the computer.

Best regards,

Dict
0
Comment
Question by:dict
  • 3
  • 3
  • 3
  • +1
10 Comments
 
LVL 17

Expert Comment

by:mokule
Comment Utility
0
 
LVL 6

Expert Comment

by:wimmeyvaert
Comment Utility
Hi,

Right from the RX-Lib StrUtils-Unit :

function ReplaceStr(const S, Srch, Replace: string): string;
var
  I: Integer;
  Source: string;
begin
  Source := S;
  Result := '';
  repeat
    I := Pos(Srch, Source);
    if I > 0 then begin
      Result := Result + Copy(Source, 1, I - 1) + Replace;
      Source := Copy(Source, I + Length(Srch), MaxInt);
    end
    else Result := Result + Source;
  until I <= 0;
end;

Used in a little application (with a TMemo, 2 TEdits and a TButton) :
When clicked on Button, in the content of the TMemo the text in first TEdit is replaced by the trext in the second one.

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := ReplaceStr( Memo1.Text, Edit1.Text, Edit2.Text);
end;
0
 
LVL 6

Expert Comment

by:wimmeyvaert
Comment Utility
Hi,

I just made a little demo-application to make use of my previous mentioned function (RX-Lib)
Just put a TButton and 4 TEdits on your form.
Call them :
    Button1: TButton;
    edtPath: TEdit;
    edtFileMask: TEdit;
    edtSearch: TEdit;
    edtRepace: TEdit;


This is a copy of my complete unit.
Just try it out and let me know if this is what you are looking for.


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    edtPath: TEdit;
    edtFileMask: TEdit;
    edtSearch: TEdit;
    edtRepace: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure ReplaceTextInFiles( Path, Mask, Search, Replace : String );
    function  ReplaceStr(const S, Srch, Replace: string): string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

Uses FileCtrl;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  ReplaceTextInFiles(edtPath.Text, edtFileMask.Text, edtSearch.Text, edtRepace.Text );
end;


procedure TForm1.ReplaceTextInFiles(Path, Mask, Search, Replace: String);
var
  sr        : TSearchRec;
  fileAttrs : Integer;
  tstrTmp   : TStringList;
begin
  Try
    fileAttrs := faAnyFile; { parameter to get any file of any type. }
    if not DirectoryExists( Path ) then
      MessageDlg('Directory does not exist : ' + Path, mtError, [mbOK], 0)
    else
    begin
      if not FindFirst( IncludeTrailingBackSlash( Path ) + Mask, fileAttrs, sr ) = 0 then
        MessageDlg('No files found with following mask : ' + Mask, mtError, [mbOK], 0)
      else
      begin
        tstrTmp := TStringList.Create; { to hold the content of the current file }
        Repeat
          tstrTmp.LoadFromFile( sr.Name ); { Load File }
          tstrTmp.Text := ReplaceStr( tstrTmp.Text, Search, Replace ); { do replacements }
          tstrTmp.SavetoFile( sr.Name ); { Save file wit hchanges. }
        until FindNext( sr ) <> 0;
        FindClose( sr );
        FreeAndNil(tstrTmp);
      end;
    end;
  except
    MessageDlg('Something went wrong in replacing the text in the files.', mtError, [mbOK], 0);
  end; { Try Except }
end;

function TForm1.ReplaceStr(const S, Srch, Replace: string): string;
var
  I: Integer;
  Source: string;
begin
  Source := S;
  Result := '';
  repeat
    I := Pos(Srch, Source);
    if I > 0 then begin
      Result := Result + Copy(Source, 1, I - 1) + Replace;
      Source := Copy(Source, I + Length(Srch), MaxInt);
    end
    else Result := Result + Source;
  until I <= 0;
end;

end.




I compiled it with no errors, but have not tested it.
Best regards,

The Mayor.
0
 
LVL 6

Expert Comment

by:wimmeyvaert
Comment Utility
Found a little bu in my repaut-loop.
It should be :


        Repeat
          tstrTmp.LoadFromFile( IncludeTrailingBackSlash( Path ) +  sr.Name ); { Load File }
          tstrTmp.Text := ReplaceStr( tstrTmp.Text, Search, Replace ); { do replacements }
          tstrTmp.SavetoFile( IncludeTrailingBackSlash( Path ) + sr.Name ); { Save file wit hchanges. }
        until FindNext( sr ) <> 0;
0
 
LVL 12

Expert Comment

by:esoftbg
Comment Utility
Download from:
http://www.geocities.com/esoftbg/
file:
Q_20932619.zip
It contains: Q_20932619.exe and Q_20932619.txt
Copy Q_20932619.txt into many different folders in all your HDD's
and then start Q_20932619.exe
If you like the exe I'll provide you the source code.

emil
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:dict
Comment Utility
Dear wimmeyvaert,

I tested your script with success! Thank you very much.

However, your script scan (search/replace) only the files of a directory or disk, not all.

Regards,

Dict
0
 

Author Comment

by:dict
Comment Utility
Dear  esoftbg,

I testes your program with success! Q_20932619.zip

You did a program very useful, congratulations for your ability as programmer!

I am asking by email ´lebronletchev´ the source code.

Thank you

Dict
0
 
LVL 12

Accepted Solution

by:
esoftbg earned 100 total points
Comment Utility
I will post here the source code, because I don't understand ´lebronletchev´ as e-mail address. If you post a real e-mail, I'll send the full code on it.

unit Unit_Q_20932619;
// I love Borland Delphi so much
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, CheckLst;

type
  TForm_Q_20932619 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    CheckListBox1: TCheckListBox;
    CheckBox1: TCheckBox;
    Label1: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
  private   { Private declarations }
    procedure Replace_Text(FName, OldText, NewText: string);
    procedure Replace_File(PathName: string; SL: TStringList);
  public    { Public declarations }
  end;

var
  Form_Q_20932619: TForm_Q_20932619;

implementation

{$R *.dfm}

procedure TForm_Q_20932619.FormCreate(Sender: TObject);
begin
  CheckListBox1.Checked[0] := True;
end;

function  Load_From_File(FName: string; StrList: TStringList): Boolean;
var
  B:      Boolean;
begin
  B := True;
  try
    try
      StrList.LoadFromFile(FName);
    except
      B := False;
    end;
  finally
    Result := B;
  end;
end;

procedure TForm_Q_20932619.Replace_Text(FName, OldText, NewText: string);
var
  B:      Boolean;
  I:      Integer;
  L:      Integer;
  P:      Integer;
  StrList:TStringList;
  S:      string;
  T:      string;
  R:      string;
begin
  StrList := TStringList.Create;
  B := False;
  try
    L := Length(OldText);
    if Load_From_File(FName, StrList) then
    for I := 0 to StrList.Count-1 do
    begin
      S := StrList.Strings[I];
      P := Pos(OldText, S);
      if (P>0) then
      begin
        T := Copy(S, 1, P-1);
        R := Copy(S, P+L, Length(S)-P-L+1);
        S := T + NewText + R;
        StrList.Strings[I] := S;
        B := True;
      end;
    end;
  finally
    if B then
    begin
      StrList.SaveToFile(FName);
      ListBox1.Items.Add(FName);
      Application.ProcessMessages;
    end;
    StrList.Destroy;
  end;
end;

procedure TForm_Q_20932619.Replace_File(PathName: string; SL: TStringList);
var
  Found:         Integer;
  Attr:          Integer;
  I:             Integer;
//  P:             Integer;
  S:             string;
  T:             string;
  FName:         string;
  DirName:       string;
  SearchRec:     TSearchRec;
  procedure Prepare_For_Replace(Name: string);
  begin
    if ((FileGetAttr(Name) and faReadOnly) > 0) then
      FileSetAttr(Name, FileGetAttr(Name) xor faReadOnly);
    if ((FileGetAttr(Name) and faHidden) > 0) then
      FileSetAttr(Name, FileGetAttr(Name) xor faHidden);
    if ((FileGetAttr(Name) and faSysFile) > 0) then
      FileSetAttr(Name, FileGetAttr(Name) xor faSysFile);
  end;
begin
  Attr := faDirectory;
  Found := FindFirst(PathName+'*.*', Attr, SearchRec);
  while (Found=0) do
  try
    if (((FileGetAttr(SearchRec.Name) and faArchive) > 0)
    or  ((FileGetAttr(SearchRec.Name) and faAnyFile) > 0)) then
    for I := 0 to SL.Count-1 do
    begin
      FName := PathName + SearchRec.Name; // SL.Strings[I];
      if FileExists(FName) then
      begin
        Prepare_For_Replace(FName);
        S := UpperCase(ExtractFileExt(FName));
        T := UpperCase(SL.Strings[I]);
        {
        P := Pos('.', T);
        Delete(T, 1, P-1);
        }
        T := UpperCase(ExtractFileExt(T));
        if (S=T) then
        begin
          Prepare_For_Replace(FName);
          // Here to be a replacement
          if (Edit1.Text<>'') then
            Replace_Text(FName, Edit1.Text, Edit2.Text);
        end;
      end;
    end;
    if ((SearchRec.Attr=2064) or (SearchRec.Attr=16))
    and (not (SearchRec.Name[1]='.')) then
    begin
      DirName := PathName + SearchRec.Name + '\';
      Replace_File(DirName, SL);
    end;
  finally
    Found := FindNext(SearchRec);
  end;
  FindClose(SearchRec);
end;

procedure TForm_Q_20932619.Button1Click(Sender: TObject);
var
  C:             Char;
  I:             Integer;
  PCRootPathName:PChar;
  DriveType:     DWORD;
  S:             string;
  SL:            TStringList;
begin
  ListBox1.Clear;
  Application.ProcessMessages;
  SL := TStringList.Create;
  try
    for I := 0 to CheckListBox1.Items.Count-1 do
      if (CheckListBox1.Checked[I]) then
        SL.Add(CheckListBox1.Items.Strings[I]);
    for C := 'A' to 'Z' do
    begin
      S := C + ':\';
      PCRootPathName := PChar(S);
      DriveType := GetDriveType(PCRootPathName);
      if (DriveType=DRIVE_FIXED) then  // DRIVE_FIXED is HDD
      begin
        ListBox1.Items.Add('Current scanned HDD is ' + S);
        Application.ProcessMessages;
        Replace_File(S, SL);
      end;
    end;
  finally
    SL.Destroy;
    ListBox1.Items.Add('Done.');
  end;
end;

procedure TForm_Q_20932619.CheckBox1Click(Sender: TObject);
var
  I:             Integer;
begin
  for I := 0 to CheckListBox1.Items.Count-1 do
    CheckListBox1.Checked[I] := CheckBox1.Checked;
end;

end.
0
 

Author Comment

by:dict
Comment Utility
Dear esoftbg,

Thank you very much. Was possible download your file by my email, yes.

Thank you again.

Dict
0
 
LVL 12

Expert Comment

by:esoftbg
Comment Utility
Dear dict,
it was very pleasant to help you. I am checking my e-mails rarely and there is always more spam than real expected e-mails, but when I saw ´lebronletchev´ as a sender of an e-mail, I understood what you mean by it.
We can accomplish this question if you accept my comment from 03/28/2004 as a solution with grade A (if you think so).
Thank you,

emil
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video discusses moving either the default database or any database to a new volume.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now