如何使用Directory.EnumerateFiles,不包括隐藏文件和系统文件

时间:2016-01-05 11:51:57

标签: c# ienumerable fileinfo

我正在枚举目录中的所有文件,以便稍后处理它们。我想排除隐藏文件和系统文件。

这是我到目前为止所做的:

IEnumerable<IGrouping<string, string>> files;

files = Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories)
       .Where(f => (new FileInfo(f).Attributes & FileAttributes.Hidden & FileAttributes.System) == 0)
       .GroupBy(Path.GetDirectoryName);

但是,如果我查看结果,我仍然会隐藏并包含系统文件:

foreach (var folder in files)
{
    foreach (var file in folder)
    {
        // value for file here still shows hidden/system file paths
    }
}

我发现this question有一个与Jerome类似的例子,但我甚至无法编译。

我做错了什么?

3 个答案:

答案 0 :(得分:9)

.Where(f => (new FileInfo(f).Attributes & FileAttributes.Hidden & FileAttributes.System) == 0)

由于FileAttributes值是标志,它们在位级别上是分离的,因此您可以正确组合它们。因此,FileAttributes.Hidden & FileAttributes.System始终为0。所以你基本上要检查以下内容:

(new FileInfo(f).Attributes & 0) == 0

由于您使用& 0部分删除了任何值,因此总是如此。

您要检查的是文件是否既没有这些标志,换句话说,如果没有两种组合的共同标志:

.Where(f => (new FileInfo(f).Attributes & (FileAttributes.Hidden | FileAttributes.System)) == 0)

您还可以使用Enum.HasFlag使其更易于理解:

.Where(f => !new FileInfo(f).Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System))

答案 1 :(得分:2)

您可以使用DirectoryInfo和FileInfo大量简化代码,例如:

var mask= FileAttributes.Hidden | FileAttributes.System;

var di=new DirectoryInfo(sourcePath);
var files=di.EnumerateFiles("*", SearchOption.AllDirectories)
            .Where(fi=>fi.Attributes & mask == 0)
            .GroupBy(fi=>fi.DirectoryName);

您的原始代码尝试在没有公共位的标志之间执行按位AND,因此返回0.因此,带Attributes的按位AND也返回0.

您要检查的掩码是系统隐藏,即FileAttributes.Hidden | FileAttributes.System。提前计算它只会使代码更清晰

答案 2 :(得分:1)

您可以使用FileSystemInfo.Attributes.HasFlag

DirectoryInfo dir = new DirectoryInfo( sourcePath );
var files = dir.EnumerateFiles("*", SearchOption.AllDirectories)
    .Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden) && !f.Attributes.HasFlag(FileAttributes.System))
    .GroupBy(f => f.DirectoryName);