Are there any clever ways to easily find a file by its name and unknown extension in C#?
I have a image folder with images of different types .jpg, .gif and .png.
And all the program knows is the name of the image, and not the extension.
Is it possible to get the file by its name, without doing some big recursive resource consuming loop?
You could use the EnumerateFiles method and specify a search pattern:
var files = Directory.EnumerateFiles(#"c:\work", "somefilename.*");
This will of course return an IEnumerable<string> of all files that match this search pattern. If you know there can only be one, or wanted to get the first in the list, just chain it with LINQ to further filter the results.
Yes, it is possible. Use overloaded Directory.GetFiles method which accepts search pattern as second parameter:
string[] files = Directory.GetFiles(#"c:\images", fileName + ".*");
Linq to rescue
var filenames = Directory.GetFiles(#"C:\Windows\System32").Select(f => Path.GetFileName(f)).Where(fn => fn.StartsWith("ap"));
Let linq do the looping and filtering for you
There is a couple of options:
Build your file index in advance (simple dictionary will do the
trick).
Use windows search API.
Use EnumerateFiles, altough performance wise this is similar to a bit optimized big recursion traverse.
Related
You know that in linux it's easy but I can't just understand how to do it in C# on Windows. I want to delete all files matching the wildcard f*.txt. How do I go about going that?
You can use the DirectoryInfo.EnumerateFiles function:
var dir = new DirectoryInfo(directoryPath);
foreach (var file in dir.EnumerateFiles("f*.txt")) {
file.Delete();
}
(Of course, you'll probably want to add error handling.)
I know this has already been answered and with a good answer, but there is an alternative in .NET 4.0 and higher. Use Directory.EnumerateFiles(), thus:
foreach (string f in Directory.EnumerateFiles(myDirectory,"f*.txt"))
{
File.Delete(f);
}
The disadvantage of DirectoryInfo.GetFiles() is that it returns a list of files - which 99.9% of the time is great. The disadvantage is if the folder contains tens of thousands of files (which is rare) then it becomes very slow and enumerating through the matching files is much faster.
You can use the Directory.GetFiles method with the wildcard overload. This will return all the filenames that match your pattern. You can then delete these files.
I appreciate this thread is a little old now, but if you want to use linq then
Directory.GetFiles("f:\\TestData", "*.zip", SearchOption.TopDirectoryOnly).ToList().ForEach(File.Delete);
Say I have "a.txt", "ab.txt", "c.txt" files inside C:\temp\someFolder.
I want to get all .txt files and filter "ab.txt" from results, but do it via SearchPattern only.
I would like to be able to do something like
Directory.GetFiles("C:\\temp", "*.txt -ab", System.IO.SearchOption.AllDirectories)
as opposed to do the filtering outside the GetFiles function.
Is there a way?
The searchPattern syntax is very restricted:
The search string to match against the names of files in path. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't support regular expressions.
Wildcards allow to match multiple files with a given format, but don't allow exclusion, thus this is not possible.
You will have to rely either on filtering the result of GetFiles, or use EnumerateFiles with a filter expression, similar to this answer:
Directory.EnumerateFiles("c:\\temp", "*.txt", SearchOption.AllDirectories)
.Where(f => Path.GetFileName(f) != "ab.txt")
.ToArray();
Note that this approach calls the same internal function InternalEnumeratePaths in the Directory class (see here and here), thus it should not have any performance penalty; to the contrary, it should perform even better, due to calling ToArray after the collection has been filtered. This is especially true if a large amount of files match the initial searchPattern.
Currently I am looping through my file system like this
For Each filename As String In Directory.GetFiles(sourceFolder, "*.doc")
However this is including docx files to the list of files that GetFiles returns. I wish to only search for doc files and not docx. Any idea if there is a truncate or stop search character I can use in the search pattern?
This is the default behaviour of GetFiles, you can use LINQ to do further filtering.
var files = Directory.GetFiles(#"C:\test", "*.doc")
.Where(file=> file.EndsWith(".doc", StringComparison.CurrentCultureIgnoreCase))
.ToArray();//If you want an array back
Directory.GetFiles Method (String, String)
When you use the asterisk wildcard character in a searchPattern such
as "*.txt", the number of characters in the specified extension
affects the search as follows:
If the specified extension is exactly three characters long, the method returns files with extensions that begin with the specified extension. For example, "*.xls" returns both "book.xls" and "book.xlsx".
Given the fact that you want to iterate over your files and considering the default behavior of these methods I suggest to use EnumerateFiles instead of GetFiles. In this way you could add a simple check on the extension of the current file
foreach(string filename in Directory.EnumerateFiles(sourceFolder, "*.doc"))
{
if(!filename.EndsWith("x", StringComparison.CurrentCultureIgnoreCase))
{
.....
}
}
Not elegant as the Linq only solution but still working and not creating an array of all the filenames present in the directory
I am not a C# programmer so may be there can be syntax mistake, but i think it may solve your problem.
foreach (FileInfo fi in di.GetFiles("*.doc")
.Where(fi => string.Compare(".doc", fi.Extension,
StringComparison.OrdinalIgnoreCase) == 0))
{
myFiles.Add(fi);
}
i have a project to make and i want in option 2 the user to give an extension/keyword for example and the program to search the directory for this and print all the files that include this extension/keyword and i need some help if it's possible.
Then use another overload of the Directory.GetFiles() method which accepts a search pattern as a parameter.
Check it out on MSDN. And here is an example.
var files = Directory.GetFiles(#"c:\", "*.exe");
Obviously, replace that second argument with a variable name where you store an input from a user.
Or perhaps something like:
IEnumerable<string> results = filePaths.Where(x => x.EndsWith(".exe"));
Is it possible to get the extension of a file but when you specify the entire path other than the extension? For example:
C:\Users\Administrator\Pictures\BlueHillsTest
Thanks
Directory.GetFiles will allow you to specify a wildcard for files to search:
System.IO.Directory.GetFiles(#"C:\temp\py\", "test.*")
for me, returns an array of 3 matching items. I expect an array, since the directory contains test.cover, test.py, and test.pyc.
If I use the First extension method:
System.IO.Directory.GetFiles(#"C:\temp\py\", "test.*").First()
then it only returns the first result (test.cover).
However, using the Single extension method:
System.IO.Directory.GetFiles(#"C:\temp\py\", "test.*").Single()
raises an InvalidOperationException because the "Sequence contains more than one element" (which might be what you want, depending on your circumstances).
But if I try
System.IO.Directory.GetFiles(#"C:\temp\py\", "step.*").Single()
then I get just step.py (no exception raised) because that's the only file matching step.* in that directory.
No it is not possible as you might have both BlueHillsTest.xxx and BlueHillsTest.yyy in this location. Which one do you expect to return in this case?