Link to home
Start Free TrialLog in
Avatar of myleseven
myleseven

asked on

Delete a folder recursivly

Hi there I am trying to work on a solution to delete a folder recursivly.
I have tried various solutions that have been posted up on the Net but none seem to work for me.
At the moment I have a solution that delete all files inside a folder and subfolders but does not delete folders.
I am not sure why.
The function I am using to remove folders is called RemoveDir.
It seems to be temproamental, that means that sometimes it deletes thema nd sometimes it does not.
I have wondered if this is because the folders maight be readonly.
I tried DeleteFile and this did not seem to work for Folders.


Here is an example that I found on the Net. It is typical of solutions that I am finding but they don't seem to work for me at all.

procedure DeleteFiles(sDir: string);
//Deletes all files in sDir
var
  MySearch: TSearchRec;
begin
  FindFirst(sDir+'\*.*', faAnyFile, MySearch);
   if (MySearch.Name<>'.')and
      (MySearch.Name<>'..') then
      DeleteFile(sDir+MySearch.Name);
  while FindNext(MySearch)=0 do
  begin
    if (MySearch.Name<>'.')and
      (MySearch.Name<>'..') then
      DeleteFile(sDir + '\' +MySearch.Name);  
  end;
end;

Here is a solution that I am working on.


Here is the one that I am using:

procedure TfrmUpdate.aDeleteFiles(sDir: string);
//Deletes all files in sDir
var
  MySearch: TSearchRec;
  sFile: string;
  sName : string;
begin
  sDir := IncludeTrailingBackslash(sDir);

  FindFirst(sDir+ '*.*', faAnyFile, MySearch);
  sName := MySearch.Name;
   if (sName<>'.')and (sName<>'..') then
   begin
    sFile := sDir+MySearch.Name;
    RemoveDir(sFile);
   end;
  while FindNext(MySearch)=0 do
  begin
    sName := MySearch.Name;

    if (MySearch.Name<>'.')and (MySearch.Name<>'..') then
    begin
      sFile := sDir+MySearch.Name;
      if MySearch.Attr = faDirectory then
      begin
        if not RemoveDir(sFile) then adeleteFiles(sFile);
      end else
      begin
        DeleteFile(sFile);
      end;
    end else
    begin
      sFile := trim((GoBackFilePath2(sFile,1)));
      RemoveDir(sFile);
    end;
  end;
end;


function GoBackFilePath2(sFilepath:string; iCount : integer):string;
{
Overhaul:
Date: 24/04/2006
Purpose: Now it will go back as many folders as indicated
}
var
  i,y : integer;
  sTemp : string;
begin

  if sFilepath <> '' then
  begin
    sTemp := ReverseString(sFilepath);
    y := 0;
    for i := 1 to iCount do
    begin
      y := PosEx('\',sTemp,y+1);
    end;
    result := MidStr(sFilePath,0,(length(sFilePath)-y));
  end else
  begin
    result := c_Null;
  end;
end;


The problem is I can't seem to find a function that will reliably delete a folder even if it is empty?!?
Can any one help me?

Kind regards
Myles
Avatar of Imthiyaz_ph
Imthiyaz_ph

Have a look at this site:
http://delphi.about.com/cs/adptips1999/a/bltip1199_2.htm

It shows how to delete a folder and its contents using shellapi.

Regards
Imthiyaz
ASKER CERTIFIED SOLUTION
Avatar of 2266180
2266180
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
uses ShellAPI;
...
var
  FileOp : ShFileOpStruct;
begin
ZeroMemory(@FileOp, sizeof(FileOp));
with FileOp do begin
  Wnd   := handle;
  wFunc := fo_delete;
  pFrom := 'D:\documents\Projects\MEmulator\adf'#0#0; // two #0 have to be at the end
  fFlags := fof_noconfirmation or fof_silent;
end;
if SHFileOperation(FileOp) <> 0 then ShowMessage('error');
end;
Avatar of myleseven

ASKER

Thank you both for your help - Imthiyaz_ph  and ZhaawZ
but I was looking for a recursive solution.

ciuly - Your solution worked perfectlly!
I like the little code replacement you used for IncludeTrailingBackslash
Do you mind if I ask you what does this line mean:
if findfirst(dir+'*.*',faAnyFile {$WARNINGS OFF}-faVolumeID-faSymLink {$WARNINGS ON} ,r)=0 then

I mean how come youneeded to use the : {$WARNINGS OFF}-faVolumeID-faSymLink {$WARNINGS ON}?

Also why did you need to specify:
 and faDirectory = faDirectory

And how come your use of RemoveDir worked but mine did not even though with my procedure when I called RemoveDir the folder was empty?

Kind regards
Myles
SHFileOperation() is a ShellAPI function that allows to do many things with files/folders, includilg *recursive* deleting. In my example will be deleted directory "D:\documents\Projects\MEmulator\adf" and all directories/subdirectories/files that are in it.
>> Also why did you need to specify:
>>  and faDirectory = faDirectory
It was "r.Attr and faDirectory = faDirectory" - it checks if it is a directory or a file. Then he uses DeleteDirectory() if it is a directory or DeleteFile() if it is a file.
Thanks ZHaawZ
in regards to your mentioning about the ShellAPI function. It may be that you can do recursive deleting with this function but I wanted to actually see how a recursive deleting function looked like. That is why I likeed ciuly's example.

also
in regard to and faDirectory = faDirectory

why could we not simply say
if r.Attr = faDirectory

?

kind regards
Myles :)

r.Attr can consist of several "1" bits. "And" operation checks if specific bits are set.
Here's an example with binary (not hex) values:
00010000 - faDirectory
00000001 - faReadOnly
00000010 - faHidden
if r.Attr is 00010011, it means that it is read-only hidden directory. "if r.Attr = faDirectory" will return false, because 00010011 <> 00010000. Therefore you use "and" operation (00010011 and 00010000 = 00010000) and then compare it to faDirectory
so this means that if r.Attr is only a directory and is not hidden or read only.

therefore if I tried this on a hidden or a readonly folder it will not delete it?
if you compare "r.attr = faDirectory", then it should return "false" on hidden and/or read-only folder
if you compare "r.attr and faDirectory = faDirectory", then it should return "true" on all folders
ok I sort of understand

how about this code:
if findfirst(dir+'*.*',faAnyFile {$WARNINGS OFF}-faVolumeID-faSymLink {$WARNINGS ON} ,r)=0 then

What does this line mean and why do we need it {$WARNINGS OFF}-faVolumeID-faSymLink {$WARNINGS ON}?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hey thanks for all your help Zhaawz,
I will split the points between you and ciuly.
Ciuly gave me the answer I was looking for but i will reward you with more points because of your efforts :)

kind regards
Myles
glad to help ;]
sorry for not stepping in, I'm in GMT+2 :) (so it's 9 am here now) thank you ZhaawZ for taking the lead and doing a pretty good explanation :)
(btw, I'm in GMT+2 too, heh.. well, this was a long night)