How to delete files with wildcards #154
Answer 1:
You will be sorely dissappointed, because depending on the order in which files placed into your directory structure, the deletion of a file causes the FindNext to skip existing files that match and thus you will not end up deleting all the ones you want. What you have to do is to set up a list to delete. Then once the list is setup, you can then delete them.
Note: Please note that a lot of people think that all you have to do is to build a list then delete them. This is not true. There are many files that can have a read/only attribute set etc... So, you must clear this first, otherwise the delete will fail. So, if you notice in my routine, I clear any attributes that may have been set for the file. Here is an example:
procedure DeleteTempRAW(S1: String); var SearchRec: TSearchRec; X: Integer; Path: String; ListToDelete: TStringList; Ok: Boolean; begin ListToDelete := TStringList.Create; Path := ExtractFilePath(S1); X := FindFirst(S1, faAnyFile - faDirectory - faVolumeID, SearchRec); if X = 0 then begin while X = 0 do begin ListToDelete.Add(Path + SearchRec.Name); X := FindNext(SearchRec); end; FindClose(SearchRec); end; for X := 0 to ListToDelete.Count - 1 do begin FileSetAttr(ListToDelete[X], 0); DeleteFile(ListToDelete[X]); end; ListToDelete.Free; end;
You would call it like so: DeleteTempRaw('C:\TEMP\MASTER*.*');
Tip by Anon.
Answer 2
First, fill a list with the filenames you want to delete. Here's a general purpose function to do that. Given a path (APath) and a filemask (AMask), the routine will fill AList with the full pathnames of all files matching AMask.
procedure GetFiles(APath, AMask: string; AList: TStrings); var searchRec: SysUtils.TSearchRec; begin APath := IncludeTrailingBackslash(APath); {Get all of the directories in this path} if FindFirst(APath + '*.*', faDirectory, searchRec) = 0 then repeat with searchRec do begin if (Name <> '.') and (Name <> '..') then if (Attr and faDirectory > 0) then GetFiles(APath + Name, AMask, AList); end; Application.ProcessMessages; until FindNext(searchRec) <> 0; SysUtils.FindClose(searchRec); {Get all of the files in this directory which match the file mask} if FindFirst(APath + AMask, faAnyFile, searchRec) = 0 then repeat with searchRec do begin if (Name <> '.') and (Name <> '..') then if (Attr and faDirectory <= 0) then AList.Add(APath + searchRec.Name); end; Application.ProcessMessages; until FindNext(searchRec) <> 0; SysUtils.FindClose(searchRec); end;
Here's how to use the routine:
var MyFileList: TStringList; iCnt: integer; begin MyFileList := nil; try MyFileList := TStringList.Create; {Get all files in C:\ and its subdirectories that match "Master*." (the period with nothing after it only looks for files with no extension)} GetFiles('c:\', 'Master*.', MyFileList); {Go through each file in the list and delete it} for iCnt := 0 to MyFileList.Count - 1 do bRet := DeleteFile(MyFileList[iCnt]); finally MyFileList.Free; end; end;
Tip by Anon.
Answer 3
The classic way to solve this problem is to use a FindFirst / FindNext / FindClose loop to find the files in the target directory and delete each one as you find it, something like this:
procedure DeleteFilesWithWildCard(Dir, Prefix, Suffix: String); var SRec: TSearchRec; begin { Check the passed parameter, make sure it ends in a backslash } if Length(Dir) = 0 then Exit; if Directory[Length(Dir)] <> '\' then AppendStr(Dir, '\' ); if FindFirst(Dir + Prefix + '*.' + Suffix, faAnyfile, SRec ) = 0 then try { We must call FindClose after the FindFirst succeeded, otherwise the program looses a system handle. So use a try finally block. } repeat { We have a hit. Check if it is a directory } if ( faDirectory and SRec.Attr ) = 0 then begin { It is a file, try to delete it. This may fail if the file has the read-only attribute. If it does we show a message but continue with other files if the user does not abort. } if not SysUtils.DeleteFile(Dir + SRec.Name ) then begin if MessageDlg( 'Cannot delete ' + SRec.Name + ', the file may be read-only. Do you want to abort the ' + 'operation?', mtError, [mbYes, mbNo, mbCancel], 0 ) <> mrNo then SysUtils.Abort; end; end; { Done with this hit, search for the next one. } until FindNext(SRec) <> 0; finally FindClose( SRec ); end; end;
Tip by Peter Below and Eddie Shipman
Original resource: | The Delphi Pool |
---|---|
Author: | Various |
Added: | 2010/02/22 |
Last updated: | 2010/02/22 |