views:

111

answers:

5

How do I retrieve all filenames matching a pattern in a directory? I tried this but it returns the full path instead of the filename.

Directory.GetFiles (path, "*.txt")

Do I have to manually crop the directory path off of the result? It's easy but maybe there is an even simpler solution :)

+2  A: 

Use Path.GetFileName with your code:

foreach(var file in Directory.GetFiles(path, "*.txt"))
{
   Console.WriteLine(Path.GetFileName(file));
}

Another solution:

DirectoryInfo dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.txt");
foreach(var file in files)
{
   Console.WriteLine(file.Name);
}
Giorgi
GetFileName(file.Name) probably without the `.Name`?
mafutrct
Yes, without the `.Name`. If you look at http://msdn.microsoft.com/en-us/library/07wt70x2.aspx, you'll see that it returns strings, not `FileInfo`.
Steven Sudit
Rather than complain, I've edited it so that it's correct. Look for my bill in the mail.
Steven Sudit
Anyhow, the now-standard comment about using `FileInfo` is that it's a lot of overhead for little benefit.
Steven Sudit
@Steven No need for sarcasm, I'm still a green 3k so I did not even think of editing. But thanks for your comments.
mafutrct
@mafuctrct: It's not always about you. In this case, any sarcasm was directed primarily at myself.
Steven Sudit
+1  A: 

You can use the following code to obtain the filenames:

    DirectoryInfo info  = new DirectoryInfo("C:\Test");
    FileInfo[] files = info.GetFiles("*.txt");

    foreach(FileInfo file in files)
    {
        string fileName = file.Name;
    }
Genady Sergeev
What's not so great about this is that it instantiates FileInfo instances for every file. The constructor has to do significant I/O in order to pre-fill the attributes and other such fields, so that's a lot of entirely avoidable overhead.
Steven Sudit
+5  A: 

Assuming you're using C#, the DirectoryInfo class will be of more use to you:

DirectoryInfo directory = new DirectoryInfo(path);
FileInfo[] files = directory.GetFiles("*.txt");

The FileInfo class contains a property Name which returns the name without the path.

See the DirectoryInfo documentation and the FileInfo documentation for more information.

Michael Shimmins
As sidenote: in .NET 4.0 you can get an enumerator and are faster / using less memory than the array approach when haing many files.
TomTom
@Tom I strongly doubt this is necessarily true when dealing with files. For instance, are you sure creating a DirectoryInfo (which is far a more complex object than the string of Directory.GetFiles) does not outweigh that small advantage (Enumerator vs Array) easily? --- However, it does not really matter in my case, as reading the file content does again easily outweigh retrieving the filenames.
mafutrct
Same problem here as with Genady Sergeev's answer: `FileInfo` has a lot of overhead that you probably don't want.
Steven Sudit
@mafuctrct: Look at http://msdn.microsoft.com/en-us/library/system.io.directory.enumeratefiles.aspx. It enumerates, but it returns strings. TomTom is right.
Steven Sudit
@Steven Right, now I understand what you meant. It is different from the solution presented in the answer so I got confused. Your idea is actually very nice.
mafutrct
Not mine: credit goes to Nick Miller.
Steven Sudit
+2  A: 

Do you want to recurse through subdirectories? Use Directory.EnumerateFiles:

var fileNames = Directory.EnumerateFiles(@"\", "*.*", SearchOption.AllDirectories);
Nick Miller
This is the most efficient way when you're going to go through many directories, as it returns immediately instead of trying to load everything into memory. It's new to .NET 4.0.
Steven Sudit
+1 Did not know about this
mafutrct
+4  A: 
foreach (string s in Directory.GetFiles(path, "*.txt").Select(Path.GetFileName))
       Console.WriteLine(s);
Grif
+1 for using Linq
Giorgi
for using Linq wrong? :) Try `x => Path.GetFileName (x)`
mafutrct
@mafutrct: Did you happen to try Grif's version?
Steven Sudit
Oh, wow, I apologize. I did not know this is possible. This is amazing, thanks a lot for showing!
mafutrct
The reason it works is that, strictly speaking, `Select` just needs an appropriate delegate. As in the old days, you can pass the name of a method and a delegate will be wrapped around it automatically. There's no real need for the lambda expression stuff, although that also works just fine. I doubt there's any performance difference either way.
Steven Sudit