none
Use LINQ to filter file extensions

    Question

  • I'm nearly sure I can use LINQ right in my For Each loop to filter file extensions. I want to find all the files, then filter them by extension. Something like this:

            TstExts = "|.jpg|.avi|"
            For Each AFile In My.Computer.FileSystem.GetFiles(Me.LstListSource.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.*").Where(TstExts.Contains("|" & System.IO.Path.GetExtension(AFile) & "|"))
                Debug.Print(AFile)
            Next
    

    I'm getting an error in the For Each statement because I don't how in the LINQ WHERE clause to refer back to the thing found by GetFiles. The error is caused (I think) by the last reference to "AFile" in the For Each statement.

    Thanks for any help,
    Ken

    Sunday, January 3, 2016 5:31 PM

Answers

  • I think that it is more efficient to get the list of filtered files directly, avoiding the full list, which can be large and take time. For example:

    For Each AFile In My.Computer.FileSystem.GetFiles(Me.LstListSource.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.jpg", "*.avi")
         Debug.Print(AFile)
    Next

    The list of the extensions in this call can be easily built from your TstExts, if required.

    If you really want a LINQ:

    For Each AFile In My.Computer.FileSystem.GetFiles(Me.LstListSource.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.*").Where(Function(n) TstExts.Contains("|" & LCase(Path.GetExtension(n)) & "|"))
        Debug.Print(AFile)
    Next

    For large list of filtered files, see also Directory.EnumerateFiles and DirectoryInfo.EnumerateFiles.

    • Edited by Viorel_MVP Sunday, January 3, 2016 5:57 PM
    • Marked as answer by KenKrugh Sunday, January 3, 2016 9:38 PM
    Sunday, January 3, 2016 5:51 PM

All replies

  • I think that it is more efficient to get the list of filtered files directly, avoiding the full list, which can be large and take time. For example:

    For Each AFile In My.Computer.FileSystem.GetFiles(Me.LstListSource.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.jpg", "*.avi")
         Debug.Print(AFile)
    Next

    The list of the extensions in this call can be easily built from your TstExts, if required.

    If you really want a LINQ:

    For Each AFile In My.Computer.FileSystem.GetFiles(Me.LstListSource.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.*").Where(Function(n) TstExts.Contains("|" & LCase(Path.GetExtension(n)) & "|"))
        Debug.Print(AFile)
    Next

    For large list of filtered files, see also Directory.EnumerateFiles and DirectoryInfo.EnumerateFiles.

    • Edited by Viorel_MVP Sunday, January 3, 2016 5:57 PM
    • Marked as answer by KenKrugh Sunday, January 3, 2016 9:38 PM
    Sunday, January 3, 2016 5:51 PM
  • Thanks so much for responding.

    Per the info on this page, I was hoping to avoid finding *.xlsx files when searching for *.xls, for example. After some quick testing, however, I'm now realizing that FileSystem.GetFiles (which is what I was using in my code) doesn't seem to have that problem, maybe just Directory.GetFiles does, I've not tested that. Tough teaching us old dogs new .NET tricks, too many options. ;o)

    An interesting point of note is that using the FileSystem.GetFiles with the LINQ code took 25 seconds to collect the 11791 files stored on my NAS (1-GIG hard-wired network) where as using that same FileSystem.GetFiles passing an array of the patterns (instead of *.* with the LINQ code) took 35 seconds.

    I ended up using Directory.EnumerateFiles with the LINQ code because it was fastest collecting the same 11791 files in just 13 or 14 seconds.

    Thank you again for your time!


    • Edited by KenKrugh Sunday, January 3, 2016 9:37 PM Typo
    Sunday, January 3, 2016 9:36 PM