FileFind eXtended Ver 1.10

Share your advanced PureBasic knowledge/code with the community.
kinglestat
Enthusiast
Enthusiast
Posts: 746
Joined: Fri Jul 14, 2006 8:53 pm
Location: Malta
Contact:

FileFind eXtended Ver 1.10

Post by kinglestat »

Some time ago I released to forum a filefind routine. Well, here is a utility based on that routing. For you DOS lovers

I only wrote it in the past 24 hours, and haven't found any bugs
I hope you guys find it useful

cheers

Code: Select all

; Dynamic  recursive file finder with stored results and with filters
; KingLestat
; June/2007
; PB v4.02
;
; Thanks akj / blueznl for x_matchpattern routine

Macro    FixTime ( mytime, tflag )
   i = Len ( mytime )
   
   If i = 2
      mytime + "0000"
   ElseIf i = 4
      mytime + "00"
   Else
      tflag = #False
   EndIf
EndMacro   

Macro    AssignDate ( datemin, datemax, dflag )
   dflag = #True
   szDate = FormatDate ( gszDateMask, today )
   
   If FindString ( param1, "-", 1 ) > 0
      temp = PeekS ( @param1 + 3 )
      datemin = Trim ( StringField ( temp, 1, "-" ) )
      datemax = Trim ( StringField ( temp, 2, "-" ) )
      If Len ( datemin ) <> 8 Or Len ( datemax ) <> 8
         dflag = #False 
      EndIf
   Else
      temp = Trim ( PeekS ( @param1 + 3 ) )
      If Len ( temp ) <> 8
         dflag = #False 
      Else
         If szDate > temp
            datemin = temp
            datemax = szDate
         Else
            datemin = szDate
            datemax = temp
         EndIf 
      EndIf 
   EndIf
    
EndMacro

Macro    AssignTime ( timemin, timemax, tflag )

   tflag = #True
   szTime = FormatDate ( "%hh%ii%ss", today )
   
   If FindString ( param1, "-", 1 ) > 0
      temp = PeekS ( @param1 + 3 )
      timemin = Trim ( StringField ( temp, 1, "-" ) )
      timemax = Trim ( StringField ( temp, 2, "-" ) )
      FixTime ( timemin, tflag )
      FixTime ( timemax, tflag ) 
   Else
      temp = Trim ( PeekS ( @param1 + 3 ) )
      FixTime ( temp, tflag ) 
      If szTime > temp
         timemin = temp
         timemax = szTime
      Else
         timemin = szTime
         timemax = temp
      EndIf 
   EndIf

EndMacro

Macro       CheckFDate ( tflag, pbmacro, fdate, fmin, fmax )

   If tflag = #True 
      fdate = GetFileDate ( filename, pbmacro ) 
      temp = FormatDate ( gszDateMask, fdate )
      
      If temp < fmin Or temp > fmax
         ProcedureReturn
      EndIf 
   EndIf

EndMacro

Macro       CheckFTime ( tflag, pbmacro, fdate, fmin, fmax )

    If tflag = #True
      
      If Not fdate
         fdate = GetFileDate ( filename, pbmacro )
      EndIf
      
      temp = FormatDate ( gszTimeMask, fdate )
      
      If temp < fmin Or temp > fmax
         ProcedureReturn
      EndIf 
   EndIf

EndMacro

Macro       SizeAdjuster ( num, nresult )

   mult = Right ( num, 1 )
   
   If mult = "K"
      i = 1024
   ElseIf mult = "M"
      i = 1024 * 1024
   ElseIf mult = "G"  
      i = 1024 * 1024 * 1024
   Else
      i = 1
   EndIf
   
   nresult = Val ( num ) * i

EndMacro


#FILE_BUFFER = 8192

Global            szContent.s    = ""
Global            szMask.s       = "*.*"
Global            szXMask.s      = ""
Global            szShort.s      = ""
Global            gszDateMask.s        = "%yyyy%mm%dd"
Global            gszTimeMask.s        = "%hh%ii%ss"

Global            szaDateMin.s
Global            szaDateMax.s
Global            szaTimeMin.s
Global            szaTimeMax.s
Global            szmDateMin.s
Global            szmDateMax.s
Global            szmTimeMin.s
Global            szmTimeMax.s
Global            szcDateMin.s
Global            szcDateMax.s
Global            szcTimeMin.s
Global            szcTimeMax.s

Global            szDirLine.s    = "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ"
Global            gSizeMin.l     = 0
Global            gSizeMax.l
Global            gFound.l       = 0
Global Dim        szLevel.s(128)

Global            gLen.l         = 8
Global            gRealLen.l

Global            *memBuffer.l

Global            bSize.l        = #False
Global            bXclude.l      = #False
Global            bContent.l     = #False
Global            bShort.l       = #False
Global            bcTime.l       = #False
Global            bcDate.l       = #False
Global            baTime.l       = #False
Global            baDate.l       = #False
Global            bmTime.l       = #False
Global            bmDate.l       = #False


Global NewList    xllmask.s()

Structure     stInfo
  name.s
  Size.l
  dir.l
EndStructure

Global NewList  infolist.stInfo()

Procedure.l x_matchpattern ( String.s, pattern.s, ulcase.l )
  ; check if a string matches one or more patterns  (wildcards *? separator |) 
  ; 
  ; *** check if string matches one or more patters using * and ? as wildcards 
  ; 
  ; in:     string.s                             - string to check 
  ;         pattern.s                            - pattern including wildcards * and ? and multiple patterns seperated by | 
  ;         ulcase.l    = 0 (#x_parse_matchcase) - check case 
  ;                     = 1 (#x_parse_anycase)   - don't care about case 
  ; retval: 0 or #False                          - no match 
  ;         1 or #True                           - match 
  ; 
  ; notes: 
  ; 
  ; - ? must be filled by a character, this is different in windows / dos where it can be empty 
  ; - note that an 'empty' pattern will matches an empty original 
  ; - rewrite number three, and it's still horrible 
  ; 
  If ulcase = 1 
    pattern = LCase(pattern) 
    String = LCase(String) 
  EndIf 
  ; 
  p_p = 0 
  p_l = Len(pattern) 
  s_l = Len(String) 
  ; 
  If s_l = 0                                            ; 2265 handle emtpy strings 
    If p_l = 0 
      match = #True 
    ElseIf FindString(pattern,"||",1) > 0 
      match = #True 
    ElseIf Right(pattern,1) = "|" 
      match = #True 
    Else 
      match = #False 
    EndIf 
  Else 
    Repeat 
      s_p = 1 
      ; 
      Repeat 
        ff_max = 0 
        ff_min = 0 
        p_sub.s = "" 
        p_char.s = "" 
        done = #False 
        match = #False 
        Repeat 
          p_p = p_p+1 
          p_char = Mid(pattern,p_p,1) 
          If p_char = "*" 
            ff_max = s_l 
          ElseIf p_char = "?" 
            ff_min = ff_min+1 
            If ff_min > ff_max 
              ff_max = ff_min 
            EndIf 
          ElseIf p_char = "|" 
            done = #True 
          Else 
            p_sub = p_sub+p_char 
            Repeat 
              p_char = Mid(pattern,p_p+1,1) 
              If p_char = "*" Or p_char = "?" 
                done = #True 
              ElseIf p_char = "|" 
                done = #True 
                ; p_p = p_p+1                               ; 2265 small quickfix... hope it works 
              Else 
                p_sub = p_sub+p_char 
                If p_p < p_l 
                  p_p = p_p+1 
                Else 
                  done = #True 
                EndIf 
              EndIf 
            Until done = #True 
          EndIf 
          If p_p >= p_l 
            done = #True 
          EndIf 
        Until done = #True 
        ; 
        If p_sub = "" 
          If s_l-s_p+1 <= ff_max And s_l-s_p+1 >= ff_min 
            match = #True 
          Else 
          EndIf 
          s_p = s_l+1 
        Else 
          x = FindString(String,p_sub,s_p) 
          If x > 0 
            If x-s_p > ff_max 
            ElseIf x-s_p < ff_min 
            Else 
              match = #True 
            EndIf 
            s_p = x+Len(p_sub) 
          Else 
            s_p = s_l+1 
          EndIf 
        EndIf 
      Until match = #False Or s_p = s_l+1 
      ; 
      If p_p < p_l 
        If match = #False 
          While p_p < p_l And p_char <> "|" 
            p_p = p_p+1 
            p_char = Mid(pattern,p_p,1) 
          Wend 
        Else 
          While p_p < p_l And p_char <> "|" 
            p_p = p_p+1 
            p_char = Mid(pattern,p_p,1) 
            If p_char = "|" 
            ElseIf p_char <> "*" 
              match = #False 
            EndIf 
          Wend 
        EndIf 
      EndIf 
    Until match = #True Or p_p >= p_l 
  EndIf 
  ; 
  ProcedureReturn match 
EndProcedure 

EnableExplicit

Procedure         InfoPath ( filename.s )
  
   Protected      Size.l
   Protected      fn.l
   Protected      mdaytime.l, adaytime.l, cdaytime.l
   Protected      Bytes.l
   Protected      dirpart.s
   Protected      filepart.s
   Protected      fdate.s, ftime.s
   Protected      temp.s
   Static         LastDir.s = ""
   
   If bXclude = #True
      ForEach xllmask()
         If x_matchpattern ( filename, xllmask(), #True )
            ProcedureReturn
         EndIf
      Next
   EndIf
   
   Size & 0
   mdaytime & 0
   adaytime & 0
   cdaytime & 0
   
   If bSize = #True
      Size = FileSize ( filename )
      
      If Size < gSizeMin Or Size > gSizeMax
         ProcedureReturn
      EndIf
   EndIf
  
   If bContent = #True 
      
      Protected      flag.l
      Protected      i.l, j.l, k.l
       
      fn = ReadFile ( #PB_Any, filename )
      flag = #True
      
      If fn > 0 
         fn = ReadFile ( #PB_Any, filename )
         FileBuffersSize ( fn, 0 )
         i = 0
         k = 0
          
         While Eof ( fn ) = 0
            Bytes = ReadData ( fn, *memBuffer + k, #FILE_BUFFER )
            j = Bytes + k
             
            While i < j
               If CompareMemoryString ( *memBuffer + i, @szShort, 1, gLen ) = 0
                  If bShort = #True
                     If CompareMemoryString ( *memBuffer + i, @szContent, 1, gRealLen ) = 0
                        flag = #False
                        Break
                     EndIf
                  Else
                     flag = #False
                     Break
                  EndIf 
               EndIf 
               i + 1
            Wend
            
            If Not flag Or Bytes < #FILE_BUFFER
               Break
            EndIf
            
            MoveMemory ( *memBuffer + i, *memBuffer, gRealLen )
            k = gRealLen
            
         Wend
      
         CloseFile ( fn )
      Else
         PrintN ("....cant open [" + filename + "]" )
         flag = #False
      EndIf
      
      If flag = #True
         ProcedureReturn
      EndIf
      
   EndIf
  
   CheckFDate ( bmDate, #PB_Date_Modified,   mdaytime, szmDateMin, szmDateMax )
   CheckFDate ( baDate, #PB_Date_Accessed,   adaytime, szaDateMin, szaDateMax )
   CheckFDate ( bcDate, #PB_Date_Created,    cdaytime, szcDateMin, szcDateMax )
   CheckFTime ( bmTime, #PB_Date_Modified,   mdaytime, szmTimeMin, szmTimeMax )
   CheckFTime ( bcTime, #PB_Date_Created,    cdaytime, szcTimeMin, szcTimeMax )
   CheckFTime ( baTime, #PB_Date_Accessed,   adaytime, szaTimeMin, szaTimeMax )
  
   filepart    = GetFilePart ( filename )
   dirpart     = GetPathPart ( filename )
   
   If CompareMemoryString ( @dirpart, @LastDir, 1 ) 
      AddElement ( infolist() )
      infolist()\name   = dirpart
      infolist()\dir    = #True
      LastDir = dirpart
   EndIf
   
   AddElement ( infolist() )
   infolist()\name   = filepart
   infolist()\dir    = #False
   
   If Size
      infolist()\Size   = Size
   Else
      infolist()\Size   = FileSize ( filename )
   EndIf

   gFound + 1
   
EndProcedure

Procedure         FindFileEx ( mask.l, root.s, func.l )  
  
   Protected       temp.s
   Protected       df.l
   Protected       skip.l
   Static NewList  llmask.s()
         
   If mask    
      
      Protected     i.l, j.l
      Protected     filemask.s
               
      ClearList ( llmask() )
      filemask = PeekS ( mask )
      i = 1
         
      Repeat
      
         temp = StringField ( filemask, i, ";" )
         
         If temp > ""
            AddElement ( llmask() )
            llmask() = temp
            i + 1
         Else
            Break
         EndIf
            
      ForEver
         
   EndIf
  
   ForEach llmask()
    
      df = ExamineDirectory ( #PB_Any, root, llmask() )
    
      If df > 0
         While NextDirectoryEntry ( df )
            If DirectoryEntryType ( df ) = #PB_DirectoryEntry_File
               CallFunctionFast ( func, root + "\" + DirectoryEntryName ( df ) )
            EndIf
         Wend    
      EndIf
  
   Next
    
   df = ExamineDirectory ( #PB_Any, root, "" )
  
   If df > 0
    
      skip & 0
  
         While NextDirectoryEntry ( df )
            If DirectoryEntryType ( df ) = #PB_DirectoryEntry_Directory
               skip + 1
               If skip > 2
                  temp = DirectoryEntryName ( df ) 
                  FindFileEx ( 0, root + "\" + temp, func )
               EndIf
            EndIf       
         Wend    
   EndIf
    
EndProcedure

   OpenConsole()
   
   PrintN ( "FFX - File Finder eXtra - V1.10.............(c) Terence Agius, 2007" )
   PrintN ( "" )
   
   If CountProgramParameters () > 0
   
      Define.s       param1
      Define.s       temp, temp2
      Define.s       dir
      Define.s       mult
      Define.s       Path
      Define.l       i, j, k, l
      Define.l       today, day, start
      Define.s       szDate, szTime
      Define.f       fsize
      
      param1 = ProgramParameter()
      temp = UCase ( Left ( param1, 2 ) )
      
      If temp = "-?" Or temp = "-H"
      
         PrintN ( "Usage:" )
         PrintN ( "" )
         PrintN ( "FFX is a DOS based recursive search facility with the ability to exclude files" )
         PrintN ( "and also look inside the files" )
         PrintN ( "" )
         PrintN ( "FFX {-h or -?} for help" )
         PrintN ( "FFX path i={include list} x={exclude list} s={min-max} f={content To find in file} ...." )
         PrintN ( "da=yyyymmdd-yyyymmdd, ta=hhmmss-hhmmss" )
         PrintN ( "dm=yyyymmdd-yyyymmdd, tm=hhmmss-hhmmss" )
         PrintN ( "dc=yyyymmdd-yyyymmdd, tc=hhmmss-hhmmss" )
         PrintN ( "....include and exclude lists can have multiple selection seperated by (;)")
         PrintN ( "....if only 1 number is specified with (s=) option, a min of 0 is assumed" )
         PrintN ( "....parameter (s=) can have k/m/g modifiers to specify size in KB, MB, GB respectively" )
         PrintN ( "....the parameters have no specific order, mix and match at will" )
         PrintN ( "....if i= is not specified (i=*.* is assumed)" )
         PrintN ( "....the search inside the file (if specified) is case insensitive" )
         PrintN ( "....the date (d=) and time (t=) can be use seperately or together" )
         PrintN ( "....the time format is 24 hrs (000000 to 235959")
         PrintN ( "....if only 1 date or time is enterred, FFX will use the current date/time" )
         PrintN ( "    if time/date enterred is later than current, it will use your values for max" )
         PrintN ( "    while if they are less, it will use them as minimum vales." )
         PrintN ( "    in date and time (a) = last accessed (m) = last modified and (c) created" )
         PrintN ( "" )
         PrintN ( "Examples:" )
         PrintN ( "" )
         PrintN ( "FFX c:\ i=*.exe;*.dll x=w*.exe --> Find all exe and dll files on c: and exclude w*.exe"  )
         End
      
      EndIf
      
      Path = param1
      k = Len ( Path )
      
      While Right ( Path, 1 ) = "\"
         k - 1
         Path = Left ( param1, k )
      Wend 
      
      today = Date()
      
      Repeat
         param1 = ProgramParameter()
         
         If param1 > ""
            temp  = UCase ( Left ( param1, 2 ) )
             
            If temp = "S="
               bSize = #True
              param1 = UCase ( param1 ) 
              If FindString ( param1, "-", 1 ) > 0
                  temp = PeekS ( @param1 + 2 )
                  temp2 = StringField ( temp, 1, "-" )
                  SizeAdjuster ( temp2, gSizeMin )
                  temp2 = StringField ( temp, 2, "-" )
                  SizeAdjuster ( temp2, gSizeMax ) 
               Else
                  temp = Trim ( PeekS ( @param1 + 2 ) )
                  SizeAdjuster ( temp, gSizeMax )
               EndIf
               
            ElseIf temp = "I="
               szMask = Trim ( PeekS ( @param1 + 2 ) )
            ElseIf temp = "X="
               
               bXclude = #True
               szXMask = Trim ( PeekS ( @param1 + 2 ) )
               i = 1
               
               Repeat
    
                  temp = StringField ( szXMask, i, ";" )
               
                  If temp > ""
                     AddElement ( xllmask() )
                     xllmask() = temp
                     i + 1
                     Else
                        Break
                     EndIf
                  
               ForEver
               
            ElseIf temp = "DM"
               AssignDate ( szmDateMin, szmDateMax, bmDate )
            ElseIf temp = "DA"
               AssignDate ( szaDateMin, szaDateMax, baDate )
            ElseIf temp = "DC"
               AssignDate ( szcDateMin, szcDateMax, bcDate )
            ElseIf temp = "TM"
               AssignTime ( szmTimeMin, szmTimeMax, bmTime )
            ElseIf temp = "TA"
               AssignTime ( szaTimeMin, szaTimeMax, baTime )
            ElseIf temp = "TC"
               AssignTime ( szcTimeMin, szcTimeMax, bcTime )
               
            ElseIf temp = "F=" 
               bContent = #True
               szContent = LCase ( Trim ( PeekS ( @param1 + 2 ) ) )
               *memBuffer = AllocateMemory ( #FILE_BUFFER + 32 )
               i = Len ( szContent )
               gRealLen  = i
               
               If i > 16
                  bShort = #True
                  szShort = Left ( szContent, 8 ) 
               Else
                  gLen = i 
                  szShort = szContent
               EndIf 
            EndIf   
         
         Else
            Break
         EndIf
      
      ForEver
      
      start = ElapsedMilliseconds ()
      FindFileEx ( @szMask, Path, @InfoPath() )
      
      If gFound
      
         PrintN ( "" )
         PrintN ( "<" + Path + ">" )
         j = 0
         k + 1
         
         ForEach infolist()
            If infolist()\dir
               dir = PeekS ( @infolist()\name + k ) 
               i = CountString ( dir, "\" )
                
               If j > 0
                  j = 0 
                  For l = 0 To i
                     If szLevel ( l ) = StringField ( dir, l + 1, "\" )
                        j + 1
                     Else
                        Break
                     EndIf   
                  Next 
               EndIf 
               
               While j < i 
                  temp = StringField ( dir, j + 1, "\" )
                  szLevel ( j ) = temp
                  PrintN ( Chr(195) + Left ( szDirLine, j + 1 ) + "<" + temp + ">" )
                  j + 1
               Wend 
            Else
               temp = " bytes"
               fsize = infolist()\Size
               
               If fsize > ( 1024 * 1024 * 1024 )
                  fsize / 1024
                  fsize / 1024
                  fsize / 1024
                  temp = " Gb"
               ElseIf fsize > ( 1024 * 1024 )
                  fsize / 1024
                  fsize / 1024
                  temp = "Mb"
               ElseIf fsize > 1024
                  fsize / 1024
                  temp = " kb"
               EndIf
               
               PrintN ( Chr(195) + Left ( szDirLine, j + 1 ) + "[" + infolist()\name + "  -->  " + StrF ( fsize, 2 ) + temp + " ]" )
            EndIf
            
         Next
         
         PrintN ( "" )
         temp = " milliseconds"
         fsize = ElapsedMilliseconds () - start
         If fsize > 2000
            fsize / 1000
            temp = " seconds"
         EndIf
         
         PrintN ( "Found " + Str ( gFound ) + " file(s) in " + StrF ( fsize, 2 ) + temp ) 
      Else
         PrintN ( "No files found matching your search criteria." )
      EndIf
      
   Else
      PrintN ( "Insufficient parameters" )
      PrintN ( "" )
      PrintN ( "Use -h or -? for usage" )
      PrintN ( "" )
      PrintN ( "Program Aborted." )
   EndIf

End

/code
I may not help with your coding
Just ask about mental issues!

http://www.lulu.com/spotlight/kingwolf
http://www.sen3.net