[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Delete a folder recursivly

Posted on 2006-04-30
16
Medium Priority
?
421 Views
Last Modified: 2010-04-05
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
0
Comment
Question by:myleseven
  • 8
  • 5
  • 2
  • +1
16 Comments
 
LVL 6

Expert Comment

by:Imthiyaz_ph
ID: 16575359
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
 
LVL 28

Accepted Solution

by:
2266180 earned 80 total points
ID: 16576017
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16576412
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:myleseven
ID: 16582573
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16582592
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16582614
>> 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
 

Author Comment

by:myleseven
ID: 16582808
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16582878
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
 

Author Comment

by:myleseven
ID: 16582888
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16582897
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
 

Author Comment

by:myleseven
ID: 16583133
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
 
LVL 11

Assisted Solution

by:ZhaawZ
ZhaawZ earned 120 total points
ID: 16583168
{$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
 

Author Comment

by:myleseven
ID: 16583386
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16583396
glad to help ;]
0
 
LVL 28

Expert Comment

by:2266180
ID: 16583398
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
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 16583407
(btw, I'm in GMT+2 too, heh.. well, this was a long night)
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Loops Section Overview
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

868 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