Jump to content

Recommended Posts

Posted (edited)

Hi all, 

I'm trying to make a listing of all files in subdirectories on a specific level in a folder structure. Let me explain, visually, this will help things a lot.

I have a folder structure like this:
 

ROOT
|--- SUBDIR 1
|      |---- SUBDIR 1.1
|               |----- SUBDIR 1.1.1
|                          |---- File1.ext
|               |----- SUBDIR 1.1.2
|                          |---- File2.ext
|               |----- SUBDIR 1.1.3
|                          |---- File2.ext
|               |----- SUBDIR 1.1.4
|                          |---- File2.ext
|               |----- SUBDIR 1.1.5
|                          |---- File2.ext
|      |---- SUBDIR 1.2
|               |----- SUBDIR 1.2.1
|                   .....
|      |---- SUBDIR 1.3
                    ....

I use _FileListToArrayRec twice:
- once to make an array of the specific directories I should be working at: I need all files on the x.x level, so it will go just until that depth using a negative integer for $iRecur
- once again to create an array of all files found under that directory and its subdirectories (level x.x.x\files...)

What happens now is that _FileListToArrayRec will always include all levels before the maximum depth is reached. The result would look like this

Row 0   15
Row 1   Root\Subdir 1
Row 2   Root\Subdir 2
Row 3   Root\Subdir 3
Row 4   Root\Subdir 1\Subdir 1.1
Row 5   Root\Subdir 1\Subdir 1.2
Row 6   Root\Subdir 1\Subdir 1.3
...

Needless to say that when my second function iterates over this array, it will find all files twice. Once on the x level, once again on the x.x level. There is no way for me not to use the recursive option in the second iteration, since the files are actually in a subdirectory there.

Where are the wizards of programming logic here? Since I can't seem to find a comprehensible or easily implementable solution for this issue.

Thanks in advance and kind regards,

Jan

Edited by jantograaf
Posted

Alright, I'm not marking this solved yet, but there might be a solution I just thought of.

Maybe I just need to do the first _FileListToArrayRec twice. Once on the level needed, once on a level just above that. And then write a little loop that searches and deletes all the lines of the second array from the first array? 🧐

Just thinking out loud here...

Posted (edited)

Okay, so this solved the issue. Nevermind. Just keeping this here for reference so other people can see the solution I thought best 🙂

If $ArrayDepth <= -1 Then
    ;First we fill an array with all the folders one level up
    $LevelUpFolderArray = _FileListToArrayRec($DCMFolder,"*",$FLTAR_FOLDERS,$ArrayDepth + 1,$FLTAR_SORT,$FLTAR_FULLPATH)
    ;If this provides a result (it always should, since this is only run when the $FolderArray contains any lines)
    If IsArray($LevelUpFolderArray) Then
        ;Using an DeleteCounter to keep track of the rows where we left off deleting
        ;Doing this since _BinarySearch did not work for me but the arrays ARE sorted
        Local $ArrayDeleteCounter = 0
        Local $FoundInRow = 0
        For $i = 1 To $LevelUpFolderArray[0]
            ;For each line in $LevelUpFolderArray, delete the corresponding line in $FolderArray
            $FoundInRow = _ArraySearch($FolderArray,$LevelUpFolderArray[$i],$ArrayDeleteCounter)
            If $FoundInRow > 0 Then
                ;Set the position to this found item
                $ArrayDeleteCounter = $FoundInRow
                ;Delete the row
                _ArrayDelete($FolderArray,$FoundInRow)
                ;Adjust the element count in the FolderArray
                $FolderArray[0] = $FolderArray[0] - 1
                ;Reset the FoundInRow-variable
                $FoundInRow = 0
            EndIf
        Next
    EndIf
EndIf

 

Edited by jantograaf
Included solution code...
  • Developers
Posted (edited)

@jantograaf,

You could also build your own recursive UDF to get this done. Something like this should be close:

Func FindFilesAtLevel($filepath, $targetLevel = 0, $filemask = "", $level = 1)
    If StringRight($filepath, 1) <> "\" Then $filepath &= "\"
    Local $hSearch = FileFindFirstFile($filepath & "*.*")
    If $hSearch = -1 Then
        ; ConsoleWrite("No files/directories matched the search pattern:" & $filepath & "*.*" & @CRLF)
        Return False
    EndIf
    Local $sFileName = "", $iResult = 0
    While 1
        $sFileName = FileFindNextFile($hSearch)
        If @error Then ExitLoop

        ; directory found higher level -> go one level deeper
        If ($level < $targetLevel Or $targetLevel = 0) And StringInStr(FileGetAttrib($filepath & $sFileName), "D") Then
            FindFilesAtLevel($filepath & $sFileName, $targetLevel, $filemask, $level + 1)
        EndIf

        ; File found  at appropriate level -> do what needs to be done
        If ($level = $targetLevel Or $targetLevel = 0) And Not StringInStr(FileGetAttrib($filepath & $sFileName), "D") And StringRegExp($sFileName, $filemask) Then
            ConsoleWrite('@@ FileName = ' & $filepath & $sFileName & @CRLF) ;### Debug Console
        EndIf
    WEnd
    ; Close the search handle.
    FileClose($hSearch)
EndFunc   ;==>FindFilesAtLevel

Which could be used as follows:

ConsoleWrite("! Example 1: List all file in c:\temp and subdirectories" & @CRLF)
$FindRoot = "c:\temp"
FindFilesAtLevel($FindRoot)        ; List all files from FindRoot

ConsoleWrite("! Example 2: List all file in c:\temp\*\" & @CRLF)
$FindRoot = "c:\temp"
FindFilesAtLevel($FindRoot, 2)

ConsoleWrite("! Example 2b: List all files in c:\temp\*\*" & @CRLF)
$FindRoot = "c:\temp"
FindFilesAtLevel($FindRoot, 3)

ConsoleWrite("! Example 3: List all *.JPG files in c:\temp\ and subdirectories" & @CRLF)
$FindRoot = "c:\temp"
$FindFiles = ".?\.jpg"      ; RegEx filter, use "" for all files
FindFilesAtLevel($FindRoot, 0, $FindFiles)

ConsoleWrite("! Example 3b: List all *.JPG files in c:\temp\*\*" & @CRLF)
$FindRoot = "c:\temp"
$FindFiles = ".?\.jpg"      ; RegEx filter, use "" for all files
FindFilesAtLevel($FindRoot, 3, $FindFiles)

Example 2 is what you are looking for I guess. ;) 

Jos

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

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
×
×
  • Create New...