Reputation: 589
How can I retrieve the latest write time of any descendant of a folder?
I need a method that will return the paths of all files that were modified after a specified DateTime. I figured I could save a lot of expensive disk reading by making sure the directory LastWriteTime is within the specified range before going through the trouble of iterating through its files and subdirectories.
This works in that when a file within the top level of a directory changes, the last write time of the folder is updated as well. However, the last write time does not bubble up any further than the file's immediate parent. In other words, if the grandchild file is changed, its property is updated, and so is it's father folder's, but not the grandfather.
Is there another high-level indicator I can use to accomplish this, or will I have to resort to recursing through every folder regardless of last change time?
Here is the method as it currently stands:
private void AddAllFilesOfAllSubdirsWithFilterToList(string dirPath, ref List<FileInfo> filesList, DateTime minDate)
{
// Return files in this directory level
foreach (string filePath in Directory.GetFiles(dirPath, "*.*", SearchOption.TopDirectoryOnly))
{
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.LastWriteTimeUtc > minDate)
{
filesList.Add(fileInfo);
}
}
// Return recursive searches through sudirs
foreach (string subDirPath in Directory.GetDirectories(dirPath))
{
DirectoryInfo dirInfo = new DirectoryInfo(subDirPath);
if (dirInfo.LastWriteTimeUtc > minDate)
{
GetAllFilesOfAllSubdirsWithFilter(subDirPath, ref filesList);
}
}
}
Upvotes: 2
Views: 5589
Reputation: 74365
You don't have to recurse through the directory tree. The CLR is perfectly happy to do it for you.
public FileInfo[] RecentlyWrittenFilesWithin( string path , string searchPattern , DateTime dateFrom , DateTime dateThru )
{
if ( string.IsNullOrWhiteSpace( path ) ) { throw new ArgumentException("invalid path" , "path" );}
DirectoryInfo root = new DirectoryInfo(path) ;
if ( !root.Exists ) { throw new ArgumentException( "non-existent directory" , "path" ) ; }
bool isDirectory = FileAttributes.Directory == ( FileAttributes.Directory & root.Attributes ) ;
if ( isDirectory ) { throw new ArgumentException("not a directory","path");}
FileInfo[] files = root.EnumerateFiles( searchPattern , SearchOption.AllDirectories )
.Where( fi => fi.LastWriteTime >= dateFrom && fi.LastWriteTime <= dateThru )
.ToArray()
;
return files ;
}
Depending on the context here (for instance, if you program is a a service of some sort), you could establish a FileSystemWatcher
on your root directory and monitor changes as they occur.
Upvotes: 1
Reputation: 4636
Sorry to say but I think you will have to go through all subdirectories.
Just change your SearchOption from your code above to recurse through subdirectories...
private void AddAllFilesOfAllSubdirsWithFilterToList(string dirPath, ref List<FileInfo> filesList, DateTime minDate)
{
// I'm assuming you want to clear this here... I would generally return it
// instead of passing it as ref
filesList.Clear();
// Return all files in directory tree
foreach (string filePath in Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories))
{
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.LastWriteTimeUtc > minDate)
{
filesList.Add(fileInfo);
}
}
}
Upvotes: 3