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
mylesevenAsked:
Who is Participating?
 
2266180Connect With a Mentor Commented:
and this is how to do it using delphi standard findfirst/findnext:

function deleteDirectory(dir:string; recursive:boolean):boolean;
var r:TSearchRec;
begin
  result:=true;
  if recursive then
  begin
    if dir[length(dir)]<>'\' then
      dir:=dir+'\';
    if findfirst(dir+'*.*',faAnyFile {$WARNINGS OFF}
                                    -faVolumeID-faSymLink {$WARNINGS ON}
                 ,r)=0 then
    begin
      repeat
        if (r.name<>'.') and (r.name<>'..') then
        begin
          if r.Attr and faDirectory = faDirectory then result:= result and deleteDirectory(dir+r.Name, true)
                                                  else result:= result and DeleteFile(dir+r.Name);
        end;
      until findnext(r)<>0;
      findclose(r);
    end;
  end;
  result:=result and RemoveDir(dir);
end;
0
 
Imthiyaz_phCommented:
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
0
 
ZhaawZSoftware DeveloperCommented:
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;
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
mylesevenAuthor Commented:
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
0
 
ZhaawZSoftware DeveloperCommented:
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.
0
 
ZhaawZSoftware DeveloperCommented:
>> 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.
0
 
mylesevenAuthor Commented:
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 :)

0
 
ZhaawZSoftware DeveloperCommented:
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
0
 
mylesevenAuthor Commented:
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?
0
 
ZhaawZSoftware DeveloperCommented:
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
0
 
mylesevenAuthor Commented:
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}?
0
 
ZhaawZConnect With a Mentor Software DeveloperCommented:
{$WARNINGS OFF}
{$WARNINGS ON}
These are compilier directives that says compiler to suppress warnings. If you remove them (i.e., leave only "faAnyFile - faVolumeID - faSymLink"), it will show something like this:
[Warning] Unit1.pas(31): Symbol 'faVolumeID' is specific to a platform

About "faAnyFile  - faVolumeID - faSymLink" - this means "find any file except volume id files and symbolic links".
Could be used also "faAnyFile and not (faVolumeID or faSymLink)" instead.
0
 
mylesevenAuthor Commented:
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
0
 
ZhaawZSoftware DeveloperCommented:
glad to help ;]
0
 
2266180Commented:
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 :)
0
 
ZhaawZSoftware DeveloperCommented:
(btw, I'm in GMT+2 too, heh.. well, this was a long night)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.