8

I'd like to retrieve a list of files whose extensions match a specified string exactly.

DirectoryInfo di = new DirectoryInfo(someValidPath);
List<FileInfo> myFiles = new List<FileInfo>();
foreach (FileInfo fi in di.GetFiles("*.txt"))
{
    myFiles.Add(fi);
}

I get the files with extension *.txt but I also get files with the extension *.txtx, so what I've coded amounts to getting the files whose extension starts with txt.

This isn't what I want. Do I need to grab all of the filenames and do a regular expression match to "\\.txt$" (I think), or test each filename string with .EndsWith(".txt"), etc., to accomplish this?

Thanks!

John
  • 15,990
  • 10
  • 70
  • 110
  • Yes, you do. Is it so hard, and why do you need regulare expressions? –  Apr 06 '11 at 21:19
  • 1
    Watch out, *every* answer forgets that Windows file names are case insensitive. You can get .TXT as well. Casing rules for file names are a bit nasty, you might want to check the string length. – Hans Passant Apr 06 '11 at 22:06
  • @Hans: Good point. Does Fredrik's answer handle the case insensitivity issue? – John Apr 07 '11 at 02:26
  • 1
    Erm, it's better. As I said, nasty, the file system keeps its own casing rules. Fredrik's code works if it is just .txt – Hans Passant Apr 07 '11 at 02:40

8 Answers8

4

Somewhat of a workaround, but you can filter out exact matches with the Where extesion method:

foreach (FileInfo fi in di.GetFiles("*.txt")
    .Where(fi => string.Compare(".txt", fi.Extension, StringComparison.OrdinalIgnoreCase) == 0))
{
   myFiles.Add(fi);
}

Note that this will make a case insensitive matching of the extension.

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
3

Using the AddRange feature of lists instead of doing the foreach loop and calling Add for each item returned by the expression below (which I save into the variable list).

var list = di.GetFiles("*.txt").Where(f => f.Extension == ".txt");
myFiles.AddRange(list);

I'm presuming you were just showing us a snippet of your code and myFiles already had values in it, if not, you could do instead.

List<FileInfo> myFiles = di.GetFiles("*.txt").Where(f => f.Extension == ".txt").ToList();
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
2

Regex might be overkill. Use the extension on FileInfo.

foreach (FileInfo fi in di.GetFiles("*.txt").Where(f => f.Extension == ".txt"))
{
     myFiles.Add(fi);
} 
Chandu
  • 81,493
  • 19
  • 133
  • 134
vcsjones
  • 138,677
  • 31
  • 291
  • 286
1

Try this:

DirectoryInfo di = new DirectoryInfo(someValidPath); 
List<FileInfo> myFiles =  
    (
        from file in di.GetFiles("*.txt")
        where file.Extension == ".txt"
        select file
    ).ToList();
Chandu
  • 81,493
  • 19
  • 133
  • 134
1
DirectoryInfo di = new DirectoryInfo(someValidPath);
List<FileInfo> myFiles = new List<FileInfo>();
foreach (FileInfo fi in di.GetFiles("*.txt"))
{
   if (fi.Extension == ".txt")
      myFiles.Add(fi);
}
Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
0

I had a user-supplied pattern so many of the other answers didn't suit me. I ended up with this more general purpose solution:

public string[] GetFiles(string path, string pattern)
{
    bool lastWildIsHook = false;
    if(pattern.EndsWith("?"))
    {
        pattern = pattern.Substring(0, pattern.Length - 1);
        lastWildIsHook = true;
    }
    var lastWildIndex = Math.Max(pattern.LastIndexOf("*"), pattern.LastIndexOf("?"));
    var endsWith = pattern.Length > lastWildIndex ? pattern.Substring(lastWildIndex + 1) : pattern;
    if(!lastWildIsHook)
        return Directory.GetFiles(path, pattern).Where(p => p.EndsWith(endsWith)).ToArray();
    else
        return Directory.GetFiles(path, pattern).Where(p => p.EndsWith(endsWith) || p.Substring(0, p.Length - 1).EndsWith(endsWith)).ToArray();
}
Nick Gotch
  • 9,167
  • 14
  • 70
  • 97
0

Couldn't you just add an if and check the last four characters of the filename?

MPękalski
  • 6,873
  • 4
  • 26
  • 36
0

If you are using C# 2.0 Isn't easier ?

string fileExtensionFilter = "*.txt";
            DirectoryInfo di = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
            List<FileInfo> myFiles = new List<FileInfo>();
            foreach (FileInfo fi in di.GetFiles(fileExtensionFilter))
            {
                if (fi.Extension == fileExtensionFilter.Substring(1)) myFiles.Add(fi);
            }