我需要能够从目录和子目录中获取所有文件,但我想为用户提供选择子目录深度的选项。 即,不仅仅是当前目录或所有目录,但他应该能够选择1,2,3,4目录的深度等。
我已经看过很多遍历目录树的例子,似乎没有一个能解决这个问题。就个人而言,我对递归感到困惑......(我目前正在使用它)。我不确定在递归函数中如何跟踪深度。
非常感谢任何帮助。
谢谢, 大卫
这是我当前的代码(我发现here):
static void FullDirList(DirectoryInfo dir, string searchPattern, string excludeFolders, int maxSz, string depth)
{
try
{
foreach (FileInfo file in dir.GetFiles(searchPattern))
{
if (excludeFolders != "")
if (Regex.IsMatch(file.FullName, excludeFolders, RegexOptions.IgnoreCase)) continue;
myStream.WriteLine(file.FullName);
MasterFileCounter += 1;
if (maxSz > 0 && myStream.BaseStream.Length >= maxSz)
{
myStream.Close();
myStream = new StreamWriter(nextOutPutFile());
}
}
}
catch
{
// make this a spearate streamwriter to accept files that failed to be read.
Console.WriteLine("Directory {0} \n could not be accessed!!!!", dir.FullName);
return; // We alredy got an error trying to access dir so dont try to access it again
}
MasterFolderCounter += 1;
foreach (DirectoryInfo d in dir.GetDirectories())
{
//folders.Add(d);
// if (MasterFolderCounter > maxFolders)
FullDirList(d, searchPattern, excludeFolders, maxSz, depth);
}
}
答案 0 :(得分:2)
使用maxdepth varibale,每次递归调用都可以递减,然后一旦达到所需深度就不能返回。
static void FullDirList(DirectoryInfo dir, string searchPattern, string excludeFolders, int maxSz, int maxDepth)
{
if(maxDepth == 0)
{
return;
}
try
{
foreach (FileInfo file in dir.GetFiles(searchPattern))
{
if (excludeFolders != "")
if (Regex.IsMatch(file.FullName, excludeFolders, RegexOptions.IgnoreCase)) continue;
myStream.WriteLine(file.FullName);
MasterFileCounter += 1;
if (maxSz > 0 && myStream.BaseStream.Length >= maxSz)
{
myStream.Close();
myStream = new StreamWriter(nextOutPutFile());
}
}
}
catch
{
// make this a spearate streamwriter to accept files that failed to be read.
Console.WriteLine("Directory {0} \n could not be accessed!!!!", dir.FullName);
return; // We alredy got an error trying to access dir so dont try to access it again
}
MasterFolderCounter += 1;
foreach (DirectoryInfo d in dir.GetDirectories())
{
//folders.Add(d);
// if (MasterFolderCounter > maxFolders)
FullDirList(d, searchPattern, excludeFolders, maxSz, depth - 1);
}
}
答案 1 :(得分:2)
让我们从重构代码开始,让它的工作更容易理解。
因此,这里的关键练习是以递归方式返回与所需模式匹配的所有文件,但仅返回到某个深度。我们先得到这些文件。
<delimited-identifiers/>
这简化了递归文件的工作。
但是你会注意到它没有根据public static IEnumerable<FileInfo> GetFullDirList(
DirectoryInfo dir, string searchPattern, int depth)
{
foreach (FileInfo file in dir.GetFiles(searchPattern))
{
yield return file;
}
if (depth > 0)
{
foreach (DirectoryInfo d in dir.GetDirectories())
{
foreach (FileInfo f in GetFullDirList(d, searchPattern, depth - 1))
{
yield return f;
}
}
}
}
参数排除文件。我们现在就解决这个问题吧。让我们开始构建excludeFolders
。
第一行是
FullDirList
这将获取并获取所有文件,将它们限制为 var results =
from fi in GetFullDirList(dir, searchPattern, depth)
where String.IsNullOrEmpty(excludeFolders)
|| !Regex.IsMatch(fi.FullName, excludeFolders, RegexOptions.IgnoreCase)
group fi.FullName by fi.Directory.FullName;
,然后按照它们所属的文件夹对所有文件进行分组。我们这样做是为了让我们可以做到这一点:
excludeFolders
现在我注意到你在计算 var directoriesFound = results.Count();
var filesFound = results.SelectMany(fi => fi).Count();
&amp; MasterFileCounter
。
您可以轻松地写道:
MasterFolderCounter
现在,要写出这些文件,您似乎正在尝试将文件名聚合到单独的文件中,但保留文件的最大长度( MasterFolderCounter+= results.Count();
MasterFileCounter += results.SelectMany(fi => fi).Count();
)。
以下是如何做到这一点:
maxSz
现在编写文件变得非常简单:
var aggregateByLength =
results
.SelectMany(fi => fi)
.Aggregate(new [] { new StringBuilder() }.ToList(),
(sbs, s) =>
{
var nl = s + Environment.NewLine;
if (sbs.Last().Length + nl.Length > maxSz)
{
sbs.Add(new StringBuilder(nl));
}
else
{
sbs.Last().Append(nl);
}
return sbs;
});
所以,完整的事情变成了:
foreach (var sb in aggregateByLength)
{
File.WriteAllText(nextOutPutFile(), sb.ToString());
}