Currently my application uses string[] subdirs = Directory.GetDirectories(path) to get the list of subdirectories, and now I want to extract the path to the latest (last modified) subdirectory in the list.
What is the easiest way to accomplish this?
(efficiency is not a major concern - but robustness is)
Non-recursive:
new DirectoryInfo(path).GetDirectories()
.OrderByDescending(d=>d.LastWriteTimeUtc).First();
Recursive:
new DirectoryInfo(path).GetDirectories("*",
SearchOption.AllDirectories).OrderByDescending(d=>d.LastWriteTimeUtc).First();
without using LINQ
DateTime lastHigh = new DateTime(1900,1,1);
string highDir;
foreach (string subdir in Directory.GetDirectories(path)){
DirectoryInfo fi1 = new DirectoryInfo(subdir);
DateTime created = fi1.LastWriteTime;
if (created > lastHigh){
highDir = subdir;
lastHigh = created;
}
}
Try this:
string pattern = "*.txt"
var dirInfo = new DirectoryInfo(directory);
var file = (from f in dirInfo.GetFiles(pattern)
orderby f.LastWriteTime descending
select f).First();
http://zamirsblog.blogspot.com/2012/07/c-find-most-recent-file-in-directory.html
Be warned: You might need to call Refresh() on your Directory Info object to get the correct information:
e.g. in Laramie's answer you'd edit to:
DirectoryInfo fi1 = new DirectoryInfo(subdir);
fi1.Refresh();
DateTime created = fi1.LastWriteTime;
Otherwise you might get outdated info like I did:
"Calls must be made to Refresh before attempting to get the attribute
information, or the information will be outdated."
http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.refresh(v=vs.71).aspx
You can use Directory.GetLastWriteTime (or Directory.GetLastWriteTimeUtc, it doesn't really matter in this case when you're just doing relative comparisons).
Although do you just want to look at the "modified" time as reported by the OS, or do you want to find the directory with the most recently-modified file inside it? They don't always match up (that is, the OS doesn't always update the containing directory "last modified" time when it modifies a file).
If you are building a windows service and you want to be notified when a new file or directory is created you could also use a FileSystemWatcher. Admittedly not as easy, but interesting to play with. :)
Related
I want to get the path that my application is located in. I get the physical path by following code:
string filePath = System.Web.HttpContext.Current.Request.PhysicalApplicationPath;
I get something like this as the result:
D:\\Projects\\UI\\IAC.SMS.MvcApp\\
I know that I can sepetare the string by "\" and combine them together. But is there an easy way to go one step back and get this?
D:\\Projects\\UI\\
You're looking for Directory.GetParent method.
var directoryName = Path.GetDirectoryName("D:\\Projects\\UI\\IAC.SMS.MvcApp\\");
var parentName = Directory.GetParent(directoryName).FullName;
Or
var parentName = new DirectoryInfo("D:\\Projects\\UI\\IAC.SMS.MvcApp\\").Parent.FullName;
Directory.GetParent will work in some cases, but it involves a performance penalty due to the creation of a DirectoryInfo object which will be populated with all sorts of information about the directory that may not be needed (e.g. creation time). I'd recommend Path.GetDirectoryName if all you need is the path, especially since with this method the path doesn't have to exist and you don't have to have permission to access it for the call to succeed.
var filePath = System.Web.HttpContext.Current.Request.PhysicalApplicationPath;
var parent = Path.GetDirectoryName(filePath);
I have an *.exe file in \ProgramFiles(x86)\MyAppFolder.
In x86 application I check if the file exists (64 bit system).
simple:
bool fileExists = File.Exists(#"\ProgramFiles(x86)\MyAppFolder\Manager.exe");
The result is:
"fileExists == false" (the file is really there). It's Virtualization as I understand.That issue described here Its ok.
But next code:
bool fileExists = new FileInfo("\\Path").Exists;
"fileExists == true"
Why is the result different in 1st and 2nd cases?
var controller = new ServiceController(Product.ServiceName);
_manager.Enabled = controller.Status == ServiceControllerStatus.Running;
var info = new DirectoryInfo(Assembly.GetExecutingAssembly().Location);
var s = File.Exists(#"D:\TFS\GL_SOURCES\Teklynx_LPM\Dev\Server\Debug\Manager.exe");
string pathToManager = string.Empty;
if (info.Parent != null)
{
var pathToModule = info.Parent.FullName;
pathToManager = Path.Combine(pathToModule,"Manager.exe").Replace(" ",string.Empty);
}
//works good
var fileInfo = new FileInfo(pathToManager);
var managerSeparator = new ToolStripSeparator()
{
Visible = _manager.Visible = fileInfo.Exists // true
};
//Does not work
var managerSeparator = new ToolStripSeparator()
{
Visible = _manager.Visible = File.Exists(pathToManager ) // false
};
Thanks!
This is about the only difference and it has more to do with the nature of FileInfo:
FileInfo fileInfo = new FileInfo("myFile.txt"); // non-existent file
Console.WriteLine(fileInfo.Exists); // false
File.Create("myFile.txt");
Console.WriteLine(File.Exists("myFile.txt")); // true
Console.WriteLine(fileInfo.Exists); // false
So as you can see the value of fileInfo.Exists is cached the first time you use it.
Other than that, they do the same thing behind the scenes.
There is no difference, these methods use the exact same internal helper method inside the .NET Framework. Something you can see with a decompiler or the Reference Source source code, the helper method name is File.FillAttributeInfo().
Having duplication like this in the .NET Framework is pretty unusual, not exactly a Good Thing to have more than one way to accomplish the same thing. The File class is however special, it got added after a usability study conducted when .NET 1.0 shipped. The test subjects just had the basic BCL classes to work with, like FileStream and FileInfo, and otherwise only had MSDN documentation available. The test results were not very good, the File class got added to help programmers fall in the pit of success writing very basic file manipulation code. Like File.Exists() and File.ReadAllLines().
So it doesn't have anything to do with the classes, you are just using them wrong. Like not actually using the same path. Do go easy on the forward slashes, the mapping to backward slashes happens inside Windows and is inconsistently implemented in other code. Using // certainly doesn't do what you hope it does.
I've replicated your scenario using the below Linqpad script
var f = #"C:\Program Files (x86)\MyAppFolder\manager.exe";
bool fileExists = File.Exists(f);
bool fileInfoExists = new FileInfo(f).Exists;
fileExists.Dump();
fileInfoExists.Dump();
Ran this both when the file existed and when it did not and both produced the same output each time.
Maybe try this on your system and see if you still see differences.
in your first case, the file path is incorrect, you need spaces in "Program Files (x86)".
Secondly, the Path.Combine will return a Directory path so you'll end up with something like "C:\Program Files (x86)\MyAppFolder\Manager.exe\"
so it's a bad idea.
Both methods work the same way, so make sure you check that the path is correct.
The difference between File.Exists() and new FileInfo().Exists on it's behavior when full path (directory name + file name) is long:
var f = #"C:\Program Files (x86)\MyAppFolder\many_subfolders\manager.exe";
//f.length > 260 characters
bool fileExists = File.Exists(f); //return false, even if the file exists
// Throw exception: "The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."
bool fileInfoExists = new FileInfo(f).Exists;
I just found this thread and wanted to update it as I had an issue with FileInfo vs File.Exists.
Let's take a scenario where we create a fileinfo object for a file that currently doesn't exist on a UNC share.
bool fileInfo = new FileInfo(#"\\uncshare\name\filename.txt");
At this point, the file does not exist, but if I create it using another tool (other code or outside my app) and then do this...
fileInfo.Refresh();
bool exists = fileInfo.Exists;
The result is false, it does not exist, even though it does and the fileInfo was refreshed.
To get the correct result requires..
bool exists = File.Exists(f);
Hope that helps others.
I had an idea to write some useful code so that the recently downloaded temp files like installation files and other media files can be copied to somewhere safe location before it gets deleted.
string dir = "c:\\Users\\neal\\appdata\\Local\\Temp";
string newdir = "D:\\";
var directory = new DirectoryInfo(dir);
var myFile = (from f in directory.GetFiles()
orderby f.LastAccessTime descending
select f).First();
var myDir = (from f in directory.GetDirectories()
orderby f.LastAccessTime descending
select f).First();
myFile.CopyTo(newdir, true);
The above method doesn't actually work. And I'm not sure why. I guess every file may not have access rights (installation files).
Any idea or any other logic out there?
I definitely agree that there are already proven solutions to this, however if you wish to implement something in code you should check out the FileSystemWatcher http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
This will notify your program of changes to the directory you are watching so you can take action.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
GetFiles with multiple extentions
is there a function like GetFiles that takes more then 1 file type like
DirectoryInfo di = new DirectoryInfo("c:/inetpub/wwwroot/demos");
FileInfo[] rgFiles = di.GetFiles("*.bmp, *.jpg, etc");
AFAIK, this isn't directly possible.
Instead, you can get every file, then filter the array:
HashSet<string> allowedExtensions = new HashSet<string>(extensionArray, StringComparer.OrdinalIgnoreCase);
FileInfo[] files = Array.FindAll(dirInfo.GetFiles(), f => allowedExtensions.Contains(f.Extension));
extensionArray must include . before each extension, but is case-insensitive.
Not that I know of.
I implemented the same problem like so:
DirectoryInfo di = new DirectoryInfo("c:/inetpub/wwwroot/demos");
FileInfo[] rgFiles = di.GetFiles("*.bmp")
.Union(di.GetFiles("*.jpg"))
.Union(di.GetFiles("etc"))
.ToArray();
Note that this requires the System.Linq namespace.
How to get files with multiple extensions
If you want your code to be bullet proof in the sense your file detection mechanism detects an image file not based on the extension but on the nature of the file, you'd have to to load your files as byte[] and look for a magic trail of bytes usually in the beginning of the array. Every graphical file has it's own way of manifesting itself to the software through presenting that magic value of bytes. I can post some code examples if you'd like.
No, theres not. Windows does not have a way to separate filters in the search pattern.
This could be done manually through LINQ, though.
By using the EnumerateFiles you'll get results as they come back so you don't have to wait for all the files in order to start working on the result.
var directory = new DirectoryInfo("C:\\");
var allowedExtensions = new string[] { ".jpg", ".bmp" };
var imageFiles = from file in directory.EnumerateFiles("*", SearchOption.AllDirectories)
where allowedExtensions.Contains(file.Extension.ToLower())
select file;
foreach (var file in imageFiles)
Console.WriteLine(file.FullName);
I've come across some strange behavior trying to get files that start with a certain string.
Please would someone give a working example on this:
I want to get all files in a directory that begin with a certain string, but also contain the xml extension.
for example:
apples_01.xml
apples_02.xml
pears_03.xml
I want to be able to get the files that begin with apples.
So far I have this code
DirectoryInfo taskDirectory = new DirectoryInfo(this.taskDirectoryPath);
FileInfo[] taskFiles = taskDirectory.GetFiles("*.xml");
FileInfo[] taskFiles = taskDirectory.GetFiles("apples*.xml");
var taskFiles = taskDirectory.GetFiles("*.xml").Where(p => p.Name.StartsWith("apples"));