Jump to content



Photo

UDF: Filter file(s) by attributes


  • Please log in to reply
3 replies to this topic

#1 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 04 June 2005 - 07:06 PM

I started out writing a UDF that would return a list of all files in a specified folder, in an array that could be handled by the Array standard UDF. Then, I wanted to specify a mask to match. Easy enough. Then, I wanted to filter the files by their attributes - for example, only return files (not folders) or don't return hidden files, or only return archive-flagged files, etc.

So, first I started by writing a file-filter routine, that takes a file and a filter string and returns true or false based on weather the file matches the filter:
Func _FileFilterAttrib($FileName, $Attrib)     Dim $Return=0, $FileAttrib, $i, $ch     If FileExists($FileName) Then         $Return=-1         $FileAttrib = FileGetAttrib($FileName)         For $i = 1 to StringLen($Attrib)             $ch = StringMid($Attrib,$i,1)             If StringIsUpper($ch) Then             ;This attribute must be on the list                 If not StringInStr($FileAttrib, $ch) then $Return = 0             Else             ;This attribute must not be on the list                 If StringInStr($FileAttrib, StringUpper($ch)) then $Return = 0             EndIf         Next     EndIf     Return $Return EndFunc

The way the filter works is this:
It is a string of characters, the same of which are returned by the function FileGetAttribute
If a character is uppercase, then the file MUST hast this attribute to pass the filter, and if the character is lower-case then the file must NOT have this attribute to pass the filter.
For example, the default filter 'dhs' will only return true on files that are not directory, hidden, or system flagged. The filter 'D' would only return directories, and the filter 'Dh' would return directories that are not hidden.

The next step is to wrap this in a file searching routine, that would search an entire folder, first matching based on a filename mask, then filter by attributes:
Func _FileFindAll($Path, $Mask="*", $AttribFilter='dhs')     Dim $FileList[100], $FileListSize = 0, $hndFile_Search, $CurFile     If FileIsDir($Path) Then;Path exists and is a directory         $hndFile_Search = FileFindFirstFile($Path & '\' & $Mask)         If $hndFile_Search<>-1 Then; at least 1 file/directory exists             $CurFile = FileFindNextFile($hndFile_Search)             While not @error;loop through found files                 If FileFilterAttrib($Path & '\' & $CurFile, $AttribFilter) Then;file passes attribute filter                     $FileListSize = $FileListSize + 1                     If $FileListSize > UBound($FileList) Then ReDim $FileList[$FileListSize+20];increase list size                     $FileList[$FileListSize - 1] = $CurFile                 EndIf                 $CurFile = FileFindNextFile($hndFile_Search)             WEnd             FileClose($hndFile_Search)             ReDim $FileList[$FileListSize]             Return $FileList         EndIf     EndIf     Return 0 EndFunc

Calling it is pretty self-explanitory, I think:
_FileFindAll('C:\Windows','*.exe','dhs')
returns an array where [0]=number of results, and [1]...[x] are the file names.







#2 FuryCell

FuryCell

    A cornered fox is more dangerous than a jackal!

  • Active Members
  • PipPipPipPipPipPip
  • 2,437 posts

Posted 05 June 2005 - 03:02 PM

I started out writing a UDF that would return a list of all files in a specified folder, in an array that could be handled by the Array standard UDF.  Then, I wanted to specify a mask to match.  Easy enough.  Then, I wanted to filter the files by their attributes - for example, only return files (not folders) or don't return hidden files, or only return archive-flagged files, etc.

So, first I started by writing a file-filter routine, that takes a file and a filter string and returns true or false based on weather the file matches the filter:

Func _FileFilterAttrib($FileName, $Attrib)     Dim $Return=0, $FileAttrib, $i, $ch     If FileExists($FileName) Then         $Return=-1         $FileAttrib = FileGetAttrib($FileName)         For $i = 1 to StringLen($Attrib)             $ch = StringMid($Attrib,$i,1)             If StringIsUpper($ch) Then             ;This attribute must be on the list                 If not StringInStr($FileAttrib, $ch) then $Return = 0             Else             ;This attribute must not be on the list                 If StringInStr($FileAttrib, StringUpper($ch)) then $Return = 0             EndIf         Next     EndIf     Return $Return EndFunc

The way the filter works is this:
It is a string of characters, the same of which are returned by the function FileGetAttribute
If a character is uppercase, then the file MUST hast this attribute to pass the filter, and if the character is lower-case then the file must NOT have this attribute to pass the filter.
For example, the default filter 'dhs' will only return true on files that are not directory, hidden, or system flagged.  The filter 'D' would only return directories, and the filter 'Dh' would return directories that are not hidden.

The next step is to wrap this in a file searching routine, that would search an entire folder, first matching based on a filename mask, then filter by attributes:
Func _FileFindAll($Path, $Mask="*", $AttribFilter='dhs')     Dim $FileList[100], $FileListSize = 0, $hndFile_Search, $CurFile     If FileIsDir($Path) Then;Path exists and is a directory         $hndFile_Search = FileFindFirstFile($Path & '\' & $Mask)         If $hndFile_Search<>-1 Then; at least 1 file/directory exists             $CurFile = FileFindNextFile($hndFile_Search)             While not @error;loop through found files                 If FileFilterAttrib($Path & '\' & $CurFile, $AttribFilter) Then;file passes attribute filter                     $FileListSize = $FileListSize + 1                     If $FileListSize > UBound($FileList) Then ReDim $FileList[$FileListSize+20];increase list size                     $FileList[$FileListSize - 1] = $CurFile                 EndIf                 $CurFile = FileFindNextFile($hndFile_Search)             WEnd             FileClose($hndFile_Search)             ReDim $FileList[$FileListSize]             Return $FileList         EndIf     EndIf     Return 0 EndFunc

Calling it is pretty self-explanitory, I think:
_FileFindAll('C:\Windows','*.exe','dhs')
returns an array where [0]=number of results, and [1]...[x] are the file names.

<{POST_SNAPBACK}>

Cool! :( These are very handy functions to have around.
Thanks. :(
-SolidSnake

Edited by SolidSnake, 05 June 2005 - 03:02 PM.

HKTunes:Softpedia | GoogleCodeLyricToy:Softpedia | GoogleCodeRCTunes:Softpedia | GoogleCodeMichtaToolsProgrammer n. - An ingenious device that turns caffeine into code.

#3 busysignal

busysignal

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 348 posts

Posted 25 July 2005 - 05:39 AM

It is pretty sad that I just found this post. Nice functions Blindwig.. :evil: I will have to add them to my listing of UDFs.

Cheers.. :)

#4 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 25 July 2005 - 08:03 AM

See also my _FileFindAllR() function, which uses the same principal and also searches recursively:
http://www.autoitscript.com/forum/index.php?showtopic=12835
Since that post I have come up with a better progress bar for the _FileGetTreeList() function - the one in that function is random because I couldn't think of a way to make a progress bar for an unknown number of items - but the code is not very portable as is. I had planned to re-write it and post it here, but have had other projects to work on and haven't had a chance to come back to it. It uses a recursive guessing method that doesn't always work out right (proportionally speaking) but is a lot better than just throwing random numbers out to try to make it look like I'm doing something useful :)




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users