tags:

views:

433

answers:

2

I need some help using LINQ to filer a list of files based on the file size. I have some code but it's using file.length instead of FileInfo(file).length. I don't know how to implement an object 'FileInfo' in the expression. HELP?

        {            
            IEnumerable<string> result = "*.ini,*.log,*.txt"
            .SelectMany(x => Directory.GetFiles("c:\logs", x, SearchOption.TopDirectoryOnly))
                            ;

            result = result
                .Where(x => (x.Length) > "500000")

               ;

       }
+2  A: 

You should be able to do something like this.

Using a DirectoryInfo, the GetFiles will return a collection of FileInfo instead of strings.

new DirectoryInfo(@"c:\logs")
    .GetFiles("*.ini,*.log,*.txt", SearchOption.TopDirectoryOnly)
    .Where(f => f.Length > 500000);

Of course you would always create FileInfo inline if you wanted to.

If you just wanted the filenames back..

IEnumerable<string> results = new DirectoryInfo(@"c:\logs")
    .GetFiles("*.ini,*.log,*.txt", SearchOption.TopDirectoryOnly)
    .Where(f => f.Length > 500000)
    .Select(f => f.FullName);
Quintin Robinson
I believe there is something wrong with your searchpattern :)
CasperT
thankyou, that worked, example two.
zion
@Zion, glad it worked for you! @CasperT, I didn't run the code and just used the example code provided for the pattern, not 100% if it is accurate or not.
Quintin Robinson
Look at this link:http://msdn.microsoft.com/en-us/library/aa328752(VS.71,loband).aspxUnder "Remarks".You can only apply a search pattern for one extension in most cases
CasperT
+2  A: 

Sorry. Searchpattern can not check up on multiple extensions.

See this article: http://msdn.microsoft.com/en-us/library/aa328752%28VS.71,loband%29.aspx Basicly these are your searchpattern tools:

  • "*" Zero or more characters.
  • "?" Exactly one character

There is no separator such as "OR", sadly.

You should instead use a regex pattern:

Regex filepattern = new Regex(".log|.txt|.ini");

var test = new DirectoryInfo("C:\\")
    .GetFiles("*", SearchOption.TopDirectoryOnly)
    .Where(f => f.Length > 0 && filepattern.IsMatch(f.FullName));

To illustrate what Quintin Robinson is talking about:

    var dir = new DirectoryInfo("C:\\");
    var test = dir
        .GetFiles("*.txt", SearchOption.TopDirectoryOnly)
        .Concat(dir.GetFiles("*.log", SearchOption.TopDirectoryOnly))
        .Concat(dir.GetFiles("*.ini", SearchOption.TopDirectoryOnly))
        .Where(f => f.Length > 0);

He believes that GetFiles is heavily optimized and it would be faster - especially with a directory with a lot files. I have not benchmarked it and really don't know which is fastest :)

Both methods works. I have tested them and they give the same result

CasperT
You could also concat the results of calls to GetFiles and not have to perform the regex match per file. I would like to believe the filtering on the call to GetFiles is optimized although I can't say for certain.
Quintin Robinson
I'm not sure how to do that :)
CasperT
But no matter what, wouldn't each file be compared to a pattern in one way or the other?
CasperT
To Concat you could do something along the lines of retaining the instance of the directory info and then `var foundItems = info.GetFiles(filter1).Concat(info.GetFiles(filter2))...` etc. (obviously pseudo). Anyway it would have to do some filtering and that is why I said I'm not sure of the differences but I would imagine that the GetFiles relies on some native optimized routines.
Quintin Robinson
There we go. I won't bother benchmarking though :)
CasperT
Now, don't I soon deserve that upvote? :P
CasperT
I think you should have phrased it as "Throw me a freakin' bone here!". Although I +1'd you anyway.
Quintin Robinson
Maybe change the filter to .??? :^)
hjb417