Intermittent FileDelete errors

Just starting out? Need help? Post your questions and find answers here.
NuclearFusion
User
User
Posts: 35
Joined: Wed Nov 22, 2006 2:00 pm

Intermittent FileDelete errors

Post by NuclearFusion »

Hi, the following program (PB 5.30) is called as follows:
clrbkup 3 txt d:\dir
The program then should remove the oldest files having extension txt and keep the most recent 3 with that extension in the specified directory.
Now I see that filedelete often returns 0, but I can't explain it.
Here's the program

Code: Select all

; =======================================================================
; Dit programma verwijdert de oudste bestanden in een bepaalde directory.
; Het programma moet worden gestart met 3 argumenten:
;     1. het aantal te bewaren (meest recente) bestanden
;     2. de te matchen extensie (gedeelte achter de punt)
;     3. het pad van de directory waarin de bestanden staan
; =======================================================================

EnableExplicit

Define keep.i
Define ext.s
Define dir.s
Define cd.i
Define nxt.i
Define filedate.q
Define filetime.s
Define fileext.s
Define max.i
Define rc.i

OpenConsole("CLRBKUP - oudste back-ups systeemschijf verwijderen")

; Number of files to keep
If ProgramParameter(0) = ""
  MessageRequester("CLRBKUP", "Fout - eerste parameter moet aantal te bewaren back-ups aangeven!")
  End
EndIf
keep = Val(ProgramParameter(0))

; Extension to match
ext = ProgramParameter(1)
If ext = ""
  MessageRequester("CLRBKUP", "Fout - tweede parameter moet de extensie van te bewaren back-ups aangeven!")
  End
EndIf

; Name of directory to check
dir = (ProgramParameter(2))
If dir = ""
  MessageRequester("CLRBKUP", "Fout - derde parameter moet de back-up directory aangeven!")
  End
EndIf

; Open the directory
cd = ExamineDirectory(#PB_Any, dir, "*."+ext)
If cd = 0
  MessageRequester("CLRBKUP", "Fout tijdens openen van Map " + dir)
  End
EndIf 

; Put file specs in a list
NewMap fname.s()
NewList times.s()

Repeat
  
  nxt = NextDirectoryEntry(cd)
  
  ; Check for end of directory
  If nxt = 0
    Break 
  EndIf
  
  ; Skip directories
  If DirectoryEntryType(cd) = #PB_DirectoryEntry_Directory Or
     DirectoryEntryName(cd) = "." Or
     DirectoryEntryName(cd) = ".."
    Continue 
  EndIf
  
  ; Skip unmatched extension
  fileext = GetExtensionPart(DirectoryEntryName(cd))
  If fileext <> ext
    Continue
  EndIf
  
  ; Fill the lists With file info
  filedate = DirectoryEntryDate(cd, #PB_Date_Created)
  filetime = FormatDate("%yyyy%mm%dd%hh%ii%ss",filedate)
  fname(filetime) = dir + "\" + DirectoryEntryName(cd)
  AddElement(times())
  times() = filetime

ForEver

; Sort list of times descending
SortList(times(), #PB_Sort_Descending)

; Skip the files to keep
max = 0
ResetList(times())
While NextElement(times())
  max = max + 1
  If max > keep
    rc = DeleteFile(fname(times()), #PB_FileSystem_Force)
    If rc = 0
      MessageRequester("CLRBKUP", "Fout - verwijderen bestand '" + fname(times()) + "' is mislukt!")
      End
    EndIf
  EndIf 
Wend

; End program
CloseConsole()
End 
Any ideas?

Thx, Arie
Little John
Addict
Addict
Posts: 4812
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Intermittent FileDelete errors

Post by Little John »

I think the problem is here:

Code: Select all

  fname(filetime) = dir + "\" + DirectoryEntryName(cd)
  AddElement(times())
  times() = filetime
For two or more matching files with the same file time, you'll get two or more entries in your times() list, but only one entry in your fname() map. The program can only work reliably, if there is exactly one entry (containing name and time) for each matching file.

There is no need for using a map here anyway, better use a list of structures, where each structure contains the name and the time for one matching file:

Code: Select all

Structure DirEntry
   name.s
   time.i
EndStructure

NewList file.DirEntry()
Some other comments:

Code: Select all

  ; Skip directories
  If DirectoryEntryType(cd) = #PB_DirectoryEntry_Directory Or
     DirectoryEntryName(cd) = "." Or
     DirectoryEntryName(cd) = ".."
    Continue
  EndIf
Since "." and ".." are not files but directories, the following simpler code yields exactly the same result:

Code: Select all

  ; Skip directories
  If DirectoryEntryType(cd) = #PB_DirectoryEntry_Directory
    Continue
  EndIf
The following code should not be necessary, because the extensions are already filtered by ExamineDirectory().

Code: Select all

  ; Skip unmatched extension
  fileext = GetExtensionPart(DirectoryEntryName(cd))
  If fileext <> ext
    Continue
  EndIf
NuclearFusion
User
User
Posts: 35
Joined: Wed Nov 22, 2006 2:00 pm

Re: Intermittent FileDelete errors

Post by NuclearFusion »

Hi Little John,

thanks for the great answer. Indeed I missed the duplicate times, caused by creating dummy files in a hurry ;-)
Other tips appreciated as well.
Maybe I need some more coffee these days :-)

Thx again,
Arie
Post Reply