如何检索文件夹任何后代的最新写入时间?
我需要一个方法来返回在指定的DateTime之后修改的所有文件的路径。我想通过确保目录LastWriteTime在指定范围内,然后经历遍历其文件和子目录的麻烦,我可以节省大量昂贵的磁盘读数。
这适用于当目录顶层中的文件发生更改时,文件夹的上次写入时间也会更新。但是,最后写入时间不会比文件的直接父级冒出来。换句话说,如果孙子文件被更改,其属性将被更新,因此它是父文件夹,但不是祖父。
我是否可以使用另一个高级别指标来完成此任务,或者无论上次更改时间如何,我都必须在每个文件夹中递归?
以下是目前的方法:
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);
}
}
}
答案 0 :(得分:2)
很抱歉,但我认为您必须浏览所有子目录。
只需将上面的代码中的SearchOption更改为通过子目录进行递归...
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);
}
}
}
答案 1 :(得分:2)
感谢您的帮助!
摘要:因此,因为DirectoryInfo
对象上没有显示文件树中任何后代的上次写入时间的属性(仅适用于子文件),所以让CLR返回所有后代文件的集合似乎很容易使用
Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
然而,在我的情况下,这有一些性能弱点:
GetFiles
返回,让您以后过滤它们。在我的情况下,这是一个巨大的集合,我可以从中收集最近几个已更改的文件以下是我现在所拥有的:
private void AddAllFilesOfAllSubdirsWithFilterToList(ref List<FileInfo> filesList, string dirPath, DateTime startDateUtc, DateTime? optionalEndDateUtc = null, List<string> blockedDirs = null)
{
// Input validation
if (String.IsNullOrEmpty(dirPath))
{
throw new ArgumentException("Cannot search and empty path");
}
DirectoryInfo currentDir = new DirectoryInfo(dirPath);
if (!currentDir.Exists)
{
throw new DirectoryNotFoundException(dirPath + " does not exist");
}
if (filesList == null)
{
filesList = new List<FileInfo>();
}
// Set endDate; add an hour to be safe
DateTime endDateUtc = optionalEndDateUtc ?? DateTime.UtcNow.AddHours(1);
// The current folder's LastWriteTime DOES update every time a child FILE is written to,
// so if the current folder does not pass the date filter, we already know that no files within will pass, either
if (currentDir.LastWriteTimeUtc >= startDateUtc && currentDir.LastWriteTimeUtc <= endDateUtc)
{
foreach (string filePath in Directory.GetFiles(dirPath, "*.*", SearchOption.TopDirectoryOnly))
{
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.LastWriteTimeUtc > _sinceDate)
{
filesList.Add(fileInfo);
}
}
}
// Unfortunately, the current folder's LastWriteTime does NOT update every time a child FOLDER is written to,
// so we have to search ALL subdirectories regardless of the current folder's LastWriteTime
foreach (string subDirPath in Directory.GetDirectories(dirPath))
{
if (blockedDirs == null || !blockedDirs.Any(p => subDirPath.ToLower().Contains(p)))
{
AddAllFilesOfAllSubdirsWithFilterToList(ref filesList, subDirPath, startDateUtc, optionalEndDateUtc, blockedDirs);
}
}
}
答案 2 :(得分:1)
您不必通过目录树递归。 CLR非常乐意为您服务。
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 ;
}
取决于此处的上下文(例如,如果您编程的是某种服务),您可以在根目录上建立FileSystemWatcher
并监视发生的更改。