Question

I need is to implement the file recursivity in this function to get all the files inside the subdirectories.

I want to preserve the efficiency of the function (I mean to avoid the using of large loops inside folders)

How I can do it?

EDIT: Also I need to put a Boolean arg to let me select if I want enable recursivity or not.

' For Each file In Get_Files("C:\Windows", {".dll", ".ini"}) : MsgBox(file.Name) : Next

Private Function Get_Files(ByVal Path As String, ParamArray exts() As String) As List(Of IO.FileInfo)
    Return New IO.DirectoryInfo(Path).GetFiles.Where(Function(o) exts.Contains(o.Extension)).ToList
End Function

UPDATE

I need to preserve in the dotINSolution modification the eficiency of the original code which returns a list of IO.FileInfo instead a list of string:

Private Function Get_Files(ByVal Path As String, ByVal Recursive As Boolean, ParamArray exts() As String) As List(Of String) ' As List(Of IO.FileInfo)
    Select Case Recursive
        Case True : Return IO.Directory.GetFiles(Path, "*.*", IO.SearchOption.AllDirectories).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).ToList
        Case False : Return IO.Directory.GetFiles(Path, "*.*", IO.SearchOption.TopDirectoryOnly).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).ToList
    End Select
End Function

Is this possibly without doing major changes or without converting the result more than one time?

Was it helpful?

Solution

All you need to do get a list of FileInfo instead of filenames is create a new FileInfo for each file, like this:

Private Function Get_Files(ByVal rootDirectory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)
    Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
    Return IO.Directory.GetFiles(rootDirectory, "*.*", searchOpt).Where(Function(o) exts.Contains(IO.Path.GetExtension(o))).Select(Function(p) New IO.FileInfo(p)).ToList
End Function

And if you use Imports System.IO at the top of your code, you don't need to type IO. so much and it will look tidier.

EDIT:

For a case-sensitive test of the extension, you could implement the comparer in the Enumerable.Contains method:

Public Class FilenameExtensionComparer
    Implements IEqualityComparer(Of String)

    Public Function Equals1(s As String, t As String) As Boolean Implements IEqualityComparer(Of String).Equals
        Return String.Compare(s, t, StringComparison.OrdinalIgnoreCase) = 0
    End Function

    Public Function GetHashCode1(s As String) As Integer Implements IEqualityComparer(Of String).GetHashCode
        Return s.GetHashCode()
    End Function

End Class

Private Function Get_Files(ByVal rootDirectory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)
    Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
    Dim filenameExtComparer As New FilenameExtensionComparer
    Return IO.Directory.GetFiles(rootDirectory, "*.*", searchOpt).Where(Function(o) exts.Contains(IO.Path.GetExtension(o), filenameExtComparer)).Select(Function(p) New IO.FileInfo(p)).ToList
End Function

I sense feature-creep in this question ;) You should have a look at the documentation for the .NET methods which are used and see if they have overloads which are useful to you.

EDIT 2: Oops, I see you wanted case-insensitivity. I adjusted the comparer appropriately.

OTHER TIPS

This should do the trick for you :)

Private Function Get_Files(ByVal Path As String, ParamArray exts() As String) As List(Of IO.FileInfo)
    Return Directory.GetFiles(Path, "*.*", SearchOption.AllDirectories).Where(Function(o) exts.Contains(Path.GetExtension(o))).ToList
End Function

Edit, With Optional recursivity:

Private Function Get_Files(ByVal Path As String, Byval searchOption As System.IO.SearchOption, ParamArray exts() As String) As List(Of IO.FileInfo)
    Return Directory.GetFiles(Path, "*.*", searchOption).Where(Function(o) exts.Contains(Path.GetExtension(o))).ToList
End Function

To search in Top Directory only:

For Each file In Get_Files("C:\Windows", SearchOption.TopDirectoryOnly, {".dll", ".ini"}) : MsgBox(file.Name) : Next

To do a recursive search:

For Each file In Get_Files("C:\Windows", SearchOption.AllDirectories, {".dll", ".ini"}) : MsgBox(file.Name) : Next

Finally this is my generic function with two additional overloads to improve the usage of the function, thanks to @Andrew Morton and @dotINSolution modifications:

#Region " Get Files "

    ' [ Get Files Function ]
    '
    ' Examples :
    '
    ' For Each file In Get_Files("C:\Windows", False) : MsgBox(file.Name) : Next
    '
    ' For Each file In Get_Files("C:\Windows", True, "dll")   : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", True, ".dll")  : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", True, "*.dll") : MsgBox(file.Name) : Next
    '
    ' For Each file In Get_Files("C:\Windows", False, {"dll", "ini"})     : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", False, {".dll", ".ini"})   : MsgBox(file.Name) : Next
    ' For Each file In Get_Files("C:\Windows", False, {"*.dll", "*.ini"}) : MsgBox(file.Name) : Next

    ' Get Files {directory} {recursive}
    Private Function Get_Files(ByVal directory As String, ByVal recursive As Boolean) As List(Of IO.FileInfo)
        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
        Return IO.Directory.GetFiles(directory, "*", searchOpt).Select(Function(p) New IO.FileInfo(p)).ToList
    End Function

    ' Get Files {directory} {recursive} {ext}
    Private Function Get_Files(ByVal directory As String, ByVal recursive As Boolean, ext As String) As List(Of IO.FileInfo)

        If ext.StartsWith("*") Then
            ext = ext.Substring(1, ext.Length - 1)
        ElseIf Not ext = "*" AndAlso Not ext.StartsWith(".") Then
            ext = ("." & ext)
        ElseIf ext = "*" Then
            ext = Nothing
        End If

        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
        Return IO.Directory.GetFiles(directory, "*" & ext, searchOpt).Select(Function(p) New IO.FileInfo(p)).ToList

    End Function

    ' Get Files {directory} {recursive} {exts()}
    Private Function Get_Files(ByVal directory As String, ByVal recursive As Boolean, ParamArray exts() As String) As List(Of IO.FileInfo)

        Dim FileExtensions(exts.Count) As String

        Dim ExtCount As Int64 = 0

        For Each ext In exts
            If ext.StartsWith("*") Then
                FileExtensions(ExtCount) = ext.Substring(1, ext.Length - 1)
            ElseIf Not ext = "*" AndAlso Not ext.StartsWith(".") Then
                FileExtensions(ExtCount) = ("." & ext)
            ElseIf Not ext = "*" AndAlso ext.StartsWith(".") Then
                FileExtensions(ExtCount) = ext
            ElseIf ext = "*" Then
                FileExtensions(ExtCount) = Nothing
            End If
            ExtCount += 1
        Next

        Dim searchOpt As IO.SearchOption = If(recursive, IO.SearchOption.AllDirectories, IO.SearchOption.TopDirectoryOnly)
        Dim filenameExtComparer As New FilenameExtensionComparer
        Return IO.Directory.GetFiles(directory, "*.*", searchOpt).Where(Function(o) FileExtensions.Contains(IO.Path.GetExtension(o), filenameExtComparer)).Select(Function(p) New IO.FileInfo(p)).ToList

    End Function

    ' FilenameExtensionComparer
    Public Class FilenameExtensionComparer : Implements IEqualityComparer(Of String)

        Public Function Equals1(s As String, t As String) As Boolean Implements IEqualityComparer(Of String).Equals
            Return String.Compare(s, t, StringComparison.OrdinalIgnoreCase) = 0
        End Function

        Public Function GetHashCode1(s As String) As Integer Implements IEqualityComparer(Of String).GetHashCode
            Return s.GetHashCode()
        End Function

    End Class

#End Region
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top