Sign in to follow this  
Followers 0
LurchMan

problem with listing files

10 posts in this topic

Hey everyone - I'm working on a script that in one portion of it, it is suppose to list all files in a directory matching a specified search string and put it into an array. The problem I'm having is that the files are named like such:

07.05.2010_random

From what I've read using FileFindFirstFile () I can only use one wildcard on each side of a period (I tried and it didn't work using the wildcards with the search string). The code below I'm using _FileListToArray () but that appears to have the same problem. Anyone got an suggestions on how I can go about this....Listing all files and looping through the array will take forever due to the amount of files that this will be looking through..Any help is appreciated

Code:

Func _FindFiles($sFrom, $sTo) ;requires 2 dates in the format of YYYY/MM/DD
    $sPath = "C:\ppgtest" ;Debug use only
    $iBot = StringRight($sFrom, 2)
    $iTop = StringRight($sTo, 2)
    $iMon = StringMid($sFrom, 6, 2)
    $iYear = StringLeft($sFrom, 4)
    Local $aFiles[1]
    If $iMon <> StringMid($sTo, 6, 2) Then
        $rtn = MsgBox(36, "Different Months", "You have selected to zip files across 2 different months..Are you sure you wish to continue?")
        If $rtn = 7 Then
            GUISetState(@SW_SHOW)
            Return
        EndIf
    EndIf
    For $n = $iBot To $iTop
        $aTemp = _FileListToArray ($sPath,$iMon & "." & $n & "." & $iYear & "*", 1)
        If Not @error Then
            _ArrayConcatenate ($aFiles, $aTemp, 1)
        Else
            Select
                Case @error = 1
                    MsgBox (16, "Error", "Error: Invalid Search Path.")
                    GUISetState(@SW_SHOW)
                    Return
                Case @error = 4
                    MsgBox (16, "Error", "Error: No files found for specified dates.")
                    GUISetState(@SW_SHOW)
                    Return
            EndSelect
        EndIf
    Next
    _ArrayDisplay($aFiles) ;Debug use only
    Return $aFiles
EndFunc   ;==>_FindFiles

Dating a girl is just like writing software. Everything's going to work just fine in the testing lab (dating), but as soon as you have contract with a customer (marriage), then your program (life) is going to be facing new situations you never expected. You'll be forced to patch the code (admit you're wrong) and then the code (wife) will just end up all bloated and unmaintainable in the end.

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Hey everyone - I'm working on a script that in one portion of it, it is suppose to list all files in a directory matching a specified search string and put it into an array. The problem I'm having is that the files are named like such:

07.05.2010_random

From what I've read using FileFindFirstFile () I can only use one wildcard on each side of a period (I tried and it didn't work using the wildcards with the search string). The code below I'm using _FileListToArray () but that appears to have the same problem. Anyone got an suggestions on how I can go about this....Listing all files and looping through the array will take forever due to the amount of files that this will be looking through..Any help is appreciated

_FileListToArray() ought to work with those search parameters. I do see you need to append a leading zero in some cases to your search string:

$sSearch = $iMon & "." & Stringright( "0" & $n, 2) & "." & $iYear & "*"
$aTemp = _FileListToArrayZ ($sPath, $sSearch, 1)

And since you'll surely have days in the search period with no files, you need to comment out this:

Case @error = 4
                    MsgBox (16, "Error", "Error: No files found for specified dates.")
                    GUISetState(@SW_SHOW)
                    Return

Beyond that, it ought to work.

Edit: PS - If this is a new project you're working on, one where you have some choice in naming your input files, I'd keep them in a yyyy/mm/dd format, like "2010.07.20_random" as they'll then list/display chronologically. And... the docs are incorrect, you can get more creative with the wildcard strings than they imply. If you used one of the other versions of _FileListToArray that are around that allow multiple filters, they'll just internally be executing the routine multiple times same as when you're controlling the loop externally. The only thing I could think of to reduce your i/o would be a logic routine up front to try and boil your date range down to the least number of searches, one that might turn a date range of say, 2010.07.01 through 2010.07.22 into four search strings: "07.0?.2010*", "07.1?.2010*", "07.21.2010*", and "07.22.2010*".

Edited by Spiff59

Share this post


Link to post
Share on other sites

_FileListToArray() ought to work with those search parameters. I do see you need to append a leading zero in some cases to your search string:

$sSearch = $iMon & "." & Stringright( "0" & $n, 2) & "." & $iYear & "*"
$aTemp = _FileListToArrayZ ($sPath, $sSearch, 1)

And since you'll surely have days in the search period with no files, you need to comment out this:

Case @error = 4
                    MsgBox (16, "Error", "Error: No files found for specified dates.")
                    GUISetState(@SW_SHOW)
                    Return

Beyond that, it ought to work.

Edit: PS - If this is a new project you're working on, one where you have some choice in naming your input files, I'd keep them in a yyyy/mm/dd format, like "2010.07.20_random" as they'll then list/display chronologically.

Thank you for the reply..the leading zero will be there - before the date gets to the function I do a StringFormat on it and do zero padding on the month and day of the date. I tried your suggestion:

$sSearch = $iMon & "." & Stringright( "0" & $n, 2) & "." & $iYear & "*"
$aTemp = _FileListToArray ($sPath,$sSearch, 1)

And this works for some reason....Dare I ask why this works even when I do a zero padding on it before it gets there?

Thank you for the tip on the error code, and I wish this was a new project..but I have no control over the file name.


Dating a girl is just like writing software. Everything's going to work just fine in the testing lab (dating), but as soon as you have contract with a customer (marriage), then your program (life) is going to be facing new situations you never expected. You'll be forced to patch the code (admit you're wrong) and then the code (wife) will just end up all bloated and unmaintainable in the end.

Share this post


Link to post
Share on other sites

Dare I ask why this works even when I do a zero padding on it before it gets there?

You're zero-padding your $iTop/$iBot variables?

Or... you're padding the $n variable that is used to construct the search string???

Share this post


Link to post
Share on other sites

You're zero-padding your $iTop/$iBot variables?

Or... you're padding the $n variable that is used to construct the search string???

I see my error now...the zero padding won't stay when I start adding to it..correct?


Dating a girl is just like writing software. Everything's going to work just fine in the testing lab (dating), but as soon as you have contract with a customer (marriage), then your program (life) is going to be facing new situations you never expected. You'll be forced to patch the code (admit you're wrong) and then the code (wife) will just end up all bloated and unmaintainable in the end.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

I see my error now...the zero padding won't stay when I start adding to it..correct?

I'm sure the $n variable, generated as the counter in your for/next loop, does not inherit any formatting that exists in the variables used to set it's start and end values, and would need to be manually formatted for each iteration of the loop. Edited by Spiff59

Share this post


Link to post
Share on other sites

I'm sure the $n variable, generated as the counter in your for/next loop, does not inherit any formatting that exists in the variables used to set it's start and end values, and would need to be manually formatted for each iteration of the loop.

Yup..I see that now..thanks for the help everyone.


Dating a girl is just like writing software. Everything's going to work just fine in the testing lab (dating), but as soon as you have contract with a customer (marriage), then your program (life) is going to be facing new situations you never expected. You'll be forced to patch the code (admit you're wrong) and then the code (wife) will just end up all bloated and unmaintainable in the end.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Yup..I see that now..thanks for the help everyone.

I got bored...

This is what I came up with to accept a date range, and refine it into the least number of search filters to feed into _FileListToArray() to nail your files. Was a fun way to spend an hour :blink: (edit2: or two!)

#include <Array.au3> ; Not required by function
#include <Date.au3>

Global $StartDate = "2008/12/12", $EndDate = "2010/03/25"
MsgBox(1,"", "Days in range (inclusive) = " & _DateDiff("d", $StartDate, $EndDate) + 1)
$aFilter_Array = _Date_Range_Filters($StartDate, $EndDate)
$aFilter_Array = _Date_Range_Filters($StartDate, $EndDate, "YYYYMMDD")
$aFilter_Array = _Date_Range_Filters($StartDate, $EndDate, "MM.DD.YYYY")
_ArrayDisplay($aFilter_Array)
;For $x = 1 to $aFilter_Array[0]
;   _FileListToArray($sPath, $aFilter_Array[$x] & "_*", 1)
;Next
Exit

; #FUNCTION# ====================================================================================================================
; Name...........: _Date_Range_Filters
; Description ...: Accept a YYYY/MM/DD date range and compress into an array of DOS search filters
; Syntax.........: _Date_Range_Filters($sStart, $sEnd [, $sFormat])
; Parameters ....: $sStart  - Start of date range (YYYY/MM/DD)
;                  $sEnd    - End of date range (YYYY/MM/DD)
;                  $sFormat - Returned date format. "YYYY", "MM" and "DD" in any order, any or no delimiter. Default = "YYYY-MM-DD"
; Return values .: Success  - Returns a 1-dimension 1-based array containing DOS search filters
; Author ........: Spiff59
; ===============================================================================================================================
Func _Date_Range_Filters($sStart, $sEnd, $sFormat = "YYYY-MM-DD")
    Local $sArray, $iFirstMonth, $iLastMonth, $iFirstDay, $iLastDay, $sDay, $sMon
    Local $aStart = StringSplit($sStart, "/")
    Local $aEnd = StringSplit($sEnd, "/")
;   Process $sFormat string
    Local $sDelim = " & '" & StringLeft(StringRegExpReplace($sFormat, "[YyMmDd]", ""), 1) & "' & "
    $sFormat = StringSplit(StringRegExpReplace(StringRegExpReplace($sFormat, "[^YyMmDd]", ""), "(.)(\1)+", "$1"),"")
    For $x = 1 to 3
        If $sFormat[$x] = "Y" Then $sFormat[$x] = "$y"
        If $sFormat[$x] = "M" Then $sFormat[$x] = "$sMon"
        If $sFormat[$x] = "D" Then $sFormat[$x] = "$sDay"
    Next
    $sFormat = $sFormat[1] & $sDelim & $sFormat[2] & $sDelim & $sFormat[3]
;   Build array
    For $y = $aStart[1] to $aEnd[1] ; year loop
        If $y = $aStart[1] Then
            $iFirstMonth = $aStart[2]
        Else
            $iFirstMonth = 1
        EndIf
        If $y = $aEnd[1] Then
            $iLastMonth = $aEnd[2]
        Else
            $iLastMonth = 12
        EndIf
        For $m = $iFirstMonth to $iLastMonth ; month loop
            $iMaxDays = _DateDaysInMonth($y, $m)
            If $y = $aStart[1] And $m = $aStart[2] Then
                $iFirstDay = $aStart[3]
            Else
                $iFirstDay = 1
            EndIf
            If $y = $aEnd[1] And $m = $aEnd[2] Then
                $iLastDay = $aEnd[3]
            Else
                $iLastDay = $iMaxDays
            EndIf
            For $d = $iFirstDay to $iLastDay ; day loop
                If $y > $aStart[1] And $y < $aEnd[1] Then
                    $sMon = "??"
                    $m = $iLastMonth
                    $sDay = "??"
                    $d = $iMaxDays
                Else
                    $sMon = $m
                    $sMon = Stringright( "0" & $m, 2)
                    Select
                        Case $d = 1 And $iLastDay = $iMaxDays
                            $sDay = "??"
                            $d = $iMaxDays
                        Case $d = 1 And $iLastDay > 8
                            $sDay = "0?"
                            $d += 8
                        Case Not Mod($d, 10) And ($iLastDay > ($d + 8) Or $iLastDay = $iMaxDays)
                            $sDay = Int($d / 10) & "?"
                            $d += 9
                        Case Else
                            $sDay = Stringright( "0" & $d, 2)
                    EndSelect
                Endif
                $sArray &= Execute($sFormat) & "|"
            Next
        Next
    Next
    Return StringSplit(StringTrimRight($sArray, 1), "|")
EndFunc

Edit: Added _DateDiff statement to show compression ratio. In this example, 469 days are crunched into 21 search filters.

Edit2: Added format parameter and function header

Edit3: Allow input date range to span multiple years

Edited by Spiff59

Share this post


Link to post
Share on other sites

Wow...thank you lol


Dating a girl is just like writing software. Everything's going to work just fine in the testing lab (dating), but as soon as you have contract with a customer (marriage), then your program (life) is going to be facing new situations you never expected. You'll be forced to patch the code (admit you're wrong) and then the code (wife) will just end up all bloated and unmaintainable in the end.

Share this post


Link to post
Share on other sites

I changed it (post #8) again!

I made it so you can specify any delimiter in the return dates, OR, no delimiter.

I'm kinda fond of the ease/flexibility of the $sFormat variable :blink:

I do think I'm finished with the routine now.

I didn't do this entirely for altruistic reasons, I have some directories myself where the filenames contain dates.

I can stick whatever filename prefix and/or suffix onto each of the elements returned from the array and use them to find all filenames dated within a certain time period. I have many files that contain "YYYYMMDD" in the filemane, and some that have "MM-DD-YYYY" within the filename. I should be able to use this on any of them.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0