Você está na página 1de 2

; +---------------+-------------------+

; | ListFiles.pbi | Ryan 'kenmo' Touk |


; +---------------+-------------------+
; |    4.01.2011  . Creation (PureBasic 4.51)


; Count.i   = ListFiles( Directory.s, List Results.s() [, Extensions.s [, Flags.i ] ] )



; Directory:  Base folder to scan for files
;              - Trailing separator (\ or /) is recommended, but not needed

; Results:    List of type string, which will be filled with found files

; Extensions: Optional, lets you only scan for files of certain types
;              - Separate extensions by spaces (txt doc log) or 'requester style' (*.txt;*.doc;*.log)
;              - Wildcards (* and ?) will be ignored

; Flags:      Optional, can be a combination of the following
;                #ListFiles_Recursive:   Scans all sub-directories along with the base folder
;                #ListFiles_Preserve:    Keeps existing elements in the Results list (they are cleared, otherwise)
;                #ListFiles_Relative:    Returns filenames relative to the base folder (absolute paths, otherwise)
;                #ListFiles_Folders:     Includes any found folders in the Results list
;                #ListFiles_FoldersOnly: Includes folders and excludes normal files from Results
;                #ListFiles_AllowNoExt:  Includes files that have no extension (not needed if no type filter is used)


; Count:      Returned value is the total number of files (and/or folders) found
;              - If the specified path is blank or cannot be examined, the result is -1
;              - The Results list may be larger than this, if you preserve prior elements

;-
;- USER Constants

; Flags for ListFiles()


#ListFiles_Recursive   = $01 ; Recursively scans all sub-directories
#ListFiles_Preserve    = $02 ; Does not clear the specified list before scanning
#ListFiles_Relative    = $04 ; Returns results relative to the provided path
#ListFiles_Folders     = $08 ; Includes directories in scan results
#ListFiles_FoldersOnly = $10 ; Excludes files from scan results (forces IncludeFolders flag)
#ListFiles_AllowNoExt  = $20 ; Include files with no extension (ignored if no extension filter is specified)

;-
;- INTERNAL Constants

; Internal flags (not needed by user)


#xListFiles_FileFilter     = $80

; OS-dependent path separator


CompilerIf (#PB_Compiler_OS = #PB_OS_Windows)
  #xListFiles_Separator = "\"
CompilerElse
  #xListFiles_Separator = "/"
CompilerEndIf

;-
;- INTERNAL Procedures

; Internal scanning procedure (not needed by user)


Procedure.i xListFiles(Root.s, Relative.s, List Results.s(), Extensions.s, Flags.i)
  Protected Count.i, ThisPath.s, Dir.i, AddThis.i
  Protected Name.s,  Type.i,     Ext.s, Recurse.i
  
  ThisPath = Root + Relative
  Dir = ExamineDirectory(#PB_Any, ThisPath, "")
  If (Dir)
    
    ; Clear previous results
    If (Not ((Flags & #ListFiles_Preserve) Or (Relative)))
      ClearList(Results())
    EndIf
    
    Count = 0
    While (NextDirectoryEntry(Dir))
      
      ; Check directory entry
      Name    =  DirectoryEntryName(Dir)
      Type    =  DirectoryEntryType(Dir)
      AddThis = #False
      Recurse = #False
      
      ; Process folders
      If (Type = #PB_DirectoryEntry_Directory)
      
        ; Check for real directories
        If ((Name <> ".") And (Name <> ".."))
          Name + #xListFiles_Separator
          
          ; Add to Results, if specified
          If (Flags & #ListFiles_Folders)
            AddThis = #True
          EndIf
          
          ; Set Recurse flag
          If (Flags & #ListFiles_Recursive)
            Recurse = #True
          EndIf
          
        EndIf
        
      ; Process files
      Else
      
        ; Exclude from Results, if specified
        If (Not (Flags & #ListFiles_FoldersOnly))
          AddThis = #True
          
          ; Check extension, if specified
          If (Flags & #xListFiles_FileFilter)
            Ext = LCase(GetExtensionPart(Name))
            
            If (Ext)
              ; Exclude unspecified file types
              If (Not FindString(Extensions, ";" + Ext + ";", 1))
                AddThis = #False
              EndIf
            Else
              ; Exclude files with no type
              If (Not (Flags & #ListFiles_AllowNoExt))
                AddThis = #False
              EndIf
            EndIf
            
          EndIf
          
        EndIf
        
      EndIf
      
      ; Add entry to Results
      If (AddThis)
        AddElement(Results())
        If (Flags & #ListFiles_Relative)
          Results() = Relative + Name
        Else
          Results() = Root + Relative + Name
        EndIf
        Count + 1
      EndIf
      
      ; Scan sub-folder, add sub-count to current count
      If (Recurse)
        Recurse = xListFiles(Root, Relative + Name, Results(), Extensions, Flags)
        If (Recurse > 0)
          Count + Recurse
        EndIf
      EndIf
      
    Wend
    
    FinishDirectory(Dir)
  Else
    ; Invalid path
    Count = -1
  EndIf
  
  ProcedureReturn (Count)
EndProcedure

;-
;- USER Procedures

Procedure.i ListFiles(Directory.s, List Results.s(), Extensions.s = "", Flags.i = #Null)


  Protected Count.i
  
  ; Check for non-empty directory
  If (Directory)
    
    ; Append trailing path separator
    If (Right(Directory, 1) <> #xListFiles_Separator)
      Directory + #xListFiles_Separator
    EndIf
    
    ; Re-format extension list into 'ext1;ext2;ext3' format
    Extensions =       RemoveString(Extensions, ".")
    Extensions =       RemoveString(Extensions, "?")
    Extensions = LCase(RemoveString(Extensions, "*"))
    ReplaceString(Extensions, "|", ";", #PB_String_InPlace)
    ReplaceString(Extensions, " ", ";", #PB_String_InPlace)
    Extensions = Trim(Extensions, ";")
    
    ; Extension string determines FileFilter flag
    If (Extensions)
      Extensions = ";" + Extensions + ";"
      Flags | ( #xListFiles_FileFilter)
    Else
      Flags & (~#xListFiles_FileFilter)
    EndIf
    
    ; FoldersOnly flag forces Folders flag
    If (Flags & #ListFiles_FoldersOnly)
      Flags | ( #ListFiles_Folders)
    EndIf
    
    ; Call function to scan base directory
    Count = xListFiles(Directory, "", Results(), Extensions, Flags)
    
  Else
  
    ; Invalid operation
    Count = -1
    
  EndIf
  
  ProcedureReturn (Count)
EndProcedure

;-

;-
;- EXAMPLE Program

;  Quick and dirty demo program: delete if you IncludeFile this from another source!

DisableExplicit

CompilerIf (#PB_Compiler_OS = #PB_OS_Windows)


  #Warning = #MB_ICONWARNING
  #Info    = #MB_ICONINFORMATION
CompilerElse
  #Warning = #Null
  #Info    = #Null
CompilerEndIf

Global NewList MyResults.s()

OpenWindow(0, 0, 0, 480, 360, "ListFiles() Demo", #PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)

Frame3DGadget(0, 10, 10, 460, 150, "Test Parameters")


  TextGadget(1, 20, 33, 80, 20, "Directory:", #PB_Text_Center)
    StringGadget(2, 100, 30, 340, 20, "")
    ButtonGadget(3, 440, 30, 20, 20, "...")
  TextGadget(4, 20, 58, 80, 20, "Extensions:", #PB_Text_Center)
    StringGadget(5, 100, 55, 340, 20, "")
    ButtonGadget(6, 440, 55, 20, 20, "?")
  CheckBoxGadget(7, 20, 80, 140, 20, "Recursive search")
    CheckBoxGadget(8, 20, 100, 140, 20, "Relative filenames")
  CheckBoxGadget(9, 160, 80, 140, 20, "Include folders")
    CheckBoxGadget(10, 160, 100, 140, 20, "Return ONLY folders")
  CheckBoxGadget(11, 300, 80, 140, 20, "Allow files with no type")
    CheckBoxGadget(12, 300, 100, 140, 20, "Preserve existing results")
  ButtonGadget(13, 150, 125, 80, 25, "Search", #PB_Button_Default)
    ButtonGadget(14, 250, 125, 80, 25, "Clear")

Frame3DGadget(15, 10, 170, 460, 180, "Results")


  ListIconGadget(16, 20, 190, 440, 150, "File", 300)
    AddGadgetColumn(16, 1, "Size", 100)

AddKeyboardShortcut(0, #PB_Shortcut_Return, 0)

SetActiveGadget(2)

Procedure Clear()
  ClearList(MyResults())
  ClearGadgetItems(16)
EndProcedure

Procedure.s Browse()
  Path.s = PathRequester("Choose Path", GetGadgetText(2))
  If (Path)
    SetGadgetText(2, Path)
  EndIf
  ProcedureReturn (Path)
EndProcedure

Procedure Search()
  Define Path.s, Exts.s, Size.i, St.s, Flags.i, Result.i
  
  ClearGadgetItems(16)
  
  Path    = GetGadgetText(2)
  Exts    = GetGadgetText(5)
  Flags   = GetGadgetState( 7) * #ListFiles_Recursive
    Flags + GetGadgetState( 8) * #ListFiles_Relative
    Flags + GetGadgetState( 9) * #ListFiles_Folders
    Flags + GetGadgetState(10) * #ListFiles_FoldersOnly
    Flags + GetGadgetState(11) * #ListFiles_AllowNoExt
    Flags + GetGadgetState(12) * #ListFiles_Preserve
  
  If (Not Path)
    Path = Browse()
  EndIf
  
  If (Path)
  
    If (Right(Path, 1) <> #xListFiles_Separator)
      Path + #xListFiles_Separator
    EndIf
  
    Result = ListFiles(Path, MyResults(), Exts, Flags)
    
    ForEach (MyResults())
      If (Flags & #ListFiles_Relative)
        Size = FileSize(Path + MyResults())
      Else
        Size = FileSize(MyResults())
      EndIf
      
      If (Size = -2)
        St = MyResults() + #LF$ + "      . dir"
      Else
        St = MyResults() + #LF$ + Str(Size)
      EndIf
      
      AddGadgetItem(16, -1, St)
    Next
    
    If (Result = -1)
      MessageRequester("Warning", "ListFiles returned -1 (empty or invalid path).", #Warning)
    Else
      MessageRequester("Info", "Found files: " + Str(Result), #Info)
    EndIf
  
  EndIf
EndProcedure

Repeat
  
  Event = WaitWindowEvent()
  If (Event = #PB_Event_CloseWindow)
    Quit = #True
  ElseIf (Event = #PB_Event_Gadget)
    Select (EventGadget())
      Case 3 : Browse()
      Case 6 : St.s = "Enter file types to include, separated by spaces:" + #LF$ + "      txt doc log"
               St + #LF$ + #LF$ + "or 'requester style':" + #LF$ + "      *.txt;*.doc;*.log"
               St + #LF$ + #LF$ + "Note: wildcards (* and ?) will be ignored."
               MessageRequester("Extensions", St, #Info)
        
      Case 13 : Search()
      Case 14 : Clear()
    EndSelect
  ElseIf (Event = #PB_Event_Menu)
    Search()
  EndIf
  
Until (Quit)

;-

Você também pode gostar