0

I've got some experience with C# but I'm quite new to VB.

My problem is as follows: I want to make a simple program in VB that searches in a specific directory, for a .dft file. I can't wrap my head around it about how I should do this.

Ultimately, I want something like this:

Dim inputdir = "C:\MyAwesomeFolder\test.par"

Depth / level search: X

X is the input level search limit.

For Each saveAsLocation In FormMain.documentRows 'i fetch the filename from here'

    For Each foundDirectory As String In IO.Directory.GetDirectories(saveAsLocation.Filename, "*.*", IO.SearchOption.AllDirectories)
        For x As Integer = 0 To LoadedSettings.DraftSearchValue Step 1 'i fetch the int limit from here'
            For Each nestedDirectory In foundDirectory
                Dim foundFiles = Directory.GetFiles(nestedDirectory)
                For Each file In foundFiles
                    If file.EndsWith(".dft") Then
                        listOfSaveAsLocations.Add(file) 'public string list'
                    End If
                Next

            Next
        Next
    Next
Next

Ihe code stops at foundDirectory saying that the directory is invalid, which is expected as it needs a directory and not a file but I don't know how I would go around this.

I've also got an aching feeling I'm using way too many loops for this.

I also tried some good examples https://learn.microsoft.com/en-us/dotnet/api/system.io.searchoption?view=net-7.0

(C# example) Searching All Directories with SearchOption.AllDirectories

but I don't know how I would implement their method and the exact reason as to why.

EDIT: now with counter

For Each saveAsLocation In FormMain.documentRows
    counter = 0
    For Each foundDirectory As String In IO.Directory.GetDirectories(Path.GetDirectoryName(saveAsLocation.Filename), "*.*", IO.SearchOption.TopDirectoryOnly)
        For Each nestedDirectory In foundDirectory

            counter += 1
            If counter > LoadedSettings.DraftSearchValue Then
                Exit For
            End If

            Dim di As DirectoryInfo = New DirectoryInfo(foundDirectory)
            Dim directories As DirectoryInfo() = di.GetDirectories("*.*", SearchOption.TopDirectoryOnly)
            Dim files As FileInfo() = di.GetFiles(".dft", SearchOption.TopDirectoryOnly)
        Next


    Next
Next

went from SearchOption.AllDirectories to SearchOption.TopDirectoryOnly, but now a new problem has arisen: instead of iterating through the current directory to go deeper, it does the opposite instead—now it goes out of the given directory to read all others.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
ZanyZilch
  • 3
  • 2
  • Maybe `Dim inputdir = "C:\MyAwesomeFolder"` then? Or use `Dim inputdir = Path.GetDirectoryName(fullPath)`. and btw. the `For x` adds another loop to the existing ones and does not limit them. – Olivier Jacot-Descombes Jul 22 '23 at 10:47
  • thanks for the Path.GetDirectoryName it really did help me out there. – ZanyZilch Jul 22 '23 at 10:52
  • but if i can't limit them with a for-loop (for-each loop doesn't work either i think) how would i do this? – ZanyZilch Jul 22 '23 at 10:53
  • Is this one of the rare occasions where a do-while is applicable? – ZanyZilch Jul 22 '23 at 10:55
  • Or you can have a counter variable you update manually `counter += 1` and `If counter > limit Then Exit For End If`. – Olivier Jacot-Descombes Jul 22 '23 at 11:06
  • alright so i've done just that + some code adjustments of my own but now it ironically starts reading in the opposite direction – ZanyZilch Jul 22 '23 at 11:50
  • 1
    I think that the directories and files are not returned in a particular order. You must sort them if you need a particular order. Also note that [GetDirectories](https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.getdirectories) has a search option that let you recurse sub-directories, so that you will not have to call `GetDirectories` again inside the loop. – Olivier Jacot-Descombes Jul 22 '23 at 13:21

1 Answers1

0

.NET Core 2.1 and later

There is an overload of the Directory.EnumerateFiles method which allows you to specify some enumeration options, in this case we are interested in the MaxRecursionDepth, for example:

Dim eo = New EnumerationOptions With {.RecurseSubdirectories = True,
                                      .MaxRecursionDepth = 2}

Dim ff = Directory.EnumerateFiles("C:\temp", "*.txt", eo).ToList()

(Of course, you don't have to do the .ToList() at that point.)

.NET Framework

You can adapt the code from Recursive File Search in VB.NET to limit the recursion depth:

Imports System.IO

Public Class SomeMeaningfulName

    Public Shared Function GetSomeFiles(rootDir As String, extn As String, maxDepth As Integer) As List(Of String)
        Dim files As New List(Of String)
        GetSomeFilesHelper(rootDir, "*" & extn, maxDepth + 1, files)

        Return files

    End Function

    Private Shared Sub GetSomeFilesHelper(dir As String, extn As String, depthRemaining As Integer, files As List(Of String))
        files.AddRange(Directory.GetFiles(dir, extn))
        depthRemaining -= 1
        If depthRemaining > 0 Then
            For Each d In Directory.EnumerateDirectories(dir)
                GetSomeFilesHelper(d, extn, depthRemaining, files)
            Next
        End If

    End Sub

End Class

You might want to add the exception handling back in, as shown in the answer I linked to. (And maybe upvote that answer.)

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84