rxdazn
rxdazn

Reputation: 1390

LINQ nested list comprehension to get files from several folders

I am trying to get .mp3 files from multiple folders.

I can already do it for one folder through this query :

this.MusicList.ItemsSource =
                from string fileName in Directory.GetFiles(@"C:\Users\Public\Music\Sample Music")
                where System.IO.Path.GetExtension(fileName) == ".mp3"
                select new FileInfo(fileName);

Is there any other way to do it for a list of directories ?

Here is what I have tried so far (returns no results):

var paths = new Dictionary<string, string> {
            {"default_music", @"C:\Users\Public\Music\Sample Music"},
            {"alternative_folder", @"C:\tmp"}
            };

this.MusicList.ItemsSource = 
from string fileName in (from string directoryName in paths.Values select Directory.GetFiles(directoryName))
where System.IO.Path.GetExtension(fileName) == ".mp3"
select new FileInfo(fileName);

from string directoryName in paths.Values select Directory.GetFiles(directoryName); returns a {System.Linq.Enumerable.WhereSelectEnumerableIterator<string,string[]>} with my paths in its source field and its Result View contains of my .mp3 files.

Thank you

Upvotes: 1

Views: 1137

Answers (4)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236278

You can use DirectoryInfo.EnumerateFiles method which accepts search pattern. Thus you don't need to get all files and filter them via calls to Path.GetExtension

var paths = new Dictionary<string, string> {
        {"default_music", @"C:\Users\Public\Music\Sample Music"},
        {"alternative_folder", @"C:\tmp"}
     };

MusicList.ItemsSource = paths.Values.Select(p => new DirectoryInfo(p))
                             .SelectMany(d => d.EnumerateFiles("*.mp3"));

Also DirectoryInfo.EnumerateFiles returns FileInfo instances, which is also what you want.

Upvotes: 3

Greg B
Greg B

Reputation: 426

Try this

Directory.EnumerateFiles(@"C:\Users\Public\Music\Sample Music", "*.mp3", SearchOption.AllDirectories)

to return an enumerable list of .mp3's, which you can further filter or enumerate etc. This is more efficient than GetFiles() for large numbers of files and/or directories.

http://msdn.microsoft.com/en-us/library/dd383571.aspx

Upvotes: 1

JerKimball
JerKimball

Reputation: 16934

Alternate to the esteemable JaredPar that tracks if it's a File/Directory:

var basePath = @"c:\temp";
var query = 
    from entry in Directory.EnumerateFileSystemEntries(basePath, "*.*", SearchOption.AllDirectories)
    let isDirectory = Directory.Exists(entry)
    let isFile = File.Exists(entry)
    select new { isDirectory, isFile, entry};
query.Dump();

EDIT: Doh - misread question, missed the "from a set of directories" part; my shame is immeasurable. :)

Upvotes: 0

JaredPar
JaredPar

Reputation: 755239

Try the following

this.MusicList.ItemsSource =
  from path in paths
  from fileName in Directory.GetFiles(path)
  where System.IO.Path.GetExtension(fileName) == ".mp3"
  select new FileInfo(fileName);

Strict method call version

this.MusicList.ItemSource = paths
  .SelectMany(path => Directory.GetFiles(path))
  .Where(fileName => System.IO.Path.GetExtension(fileName) == ".mp3")
  .Select(fileName => new FileInfo(fileName));

Upvotes: 6

Related Questions