Directory.GetFiles()
返回所有文件,即使标记为隐藏的文件也是如此。有没有办法获取排除隐藏文件的文件列表?
Answers:
这应该为您工作:
DirectoryInfo directory = new DirectoryInfo(@"C:\temp");
FileInfo[] files = directory.GetFiles();
var filtered = files.Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden));
foreach (var f in filtered)
{
Debug.WriteLine(f);
}
Directory.GetFiles
返回一个字符串数组,因此您的代码高尔夫解决方案无法正常工作。
// check whether a file is hidden
bool isHidden = ((File.GetAttributes(filePath) & FileAttributes.Hidden) == FileAttributes.Hidden);
使用.NET 4.0和Directory.EnumerateDirectories,可以使用以下结构:
var hiddenFilesQuery = from file in Directory.EnumerateDirectories(@"c:\temp")
let info = new FileInfo(file)
where (info.Attributes & FileAttributes.Hidden) == 0
select file;
这与其他答案基本相同,除了Directory.EnumerateDirectories有点懒。但是,如果您枚举所有内容,这不是很有用。
(让这里有一个查询,但更可读)。
如果您使用的是SearchOption.TopDirectoryOnly,那么相对来说比较简单,但是如果要使用SearchOption.AllDirectories递归列出所有文件,则变得更加复杂。如果可以,请获取GetFiles,然后以只读方式过滤掉,但不幸的是,它不适用于标记为隐藏的目录。该文件夹下的文件也将列出,但与目录不同,它们不会被隐藏。
您也可以使用GetDirectories,但是再次-您不能使用SearchOption.AllDirectories递归列出所有内容,因为它还会列出位于隐藏文件夹下的文件夹,但是这些文件夹未启用hidden属性。
至少对于Tortoise svn .svn隐藏文件夹就是这种情况。它包含许多未隐藏的文件夹,但是.svn被隐藏。最后,我编写了如下函数:
SearchOption sopt = SearchOption.AllDirectories;
List<String> listFiles = new List<string>();
List<DirectoryInfo> dirs2scan = new List<DirectoryInfo>();
dirs2scan.Add(new DirectoryInfo(fromPath) );
for( ; dirs2scan.Count != 0; )
{
int scanIndex = dirs2scan.Count - 1; // Try to preserve somehow alphabetic order which GetFiles returns
// by scanning though last directory.
FileInfo[] filesInfo = dirs2scan[scanIndex].GetFiles(pattern, SearchOption.TopDirectoryOnly);
foreach (FileInfo fi in filesInfo)
{
if (bNoHidden && fi.Attributes.HasFlag(FileAttributes.Hidden))
continue;
listFiles.Add(fi.FullName);
}
if( sopt != SearchOption.AllDirectories )
break;
foreach (DirectoryInfo dir in dirs2scan[scanIndex].GetDirectories("*", SearchOption.TopDirectoryOnly))
{
if (bNoHidden && dir.Attributes.HasFlag(FileAttributes.Hidden))
continue;
dirs2scan.Add(dir);
}
dirs2scan.RemoveAt(scanIndex);
}
如果需要,可以在函数中将sopt用作参数,如果不需要,可以将其删除。
我实际上更喜欢将函数参数传递给实现我想要的功能的方法。我有一个SearchDirectory方法,该方法构成了我使用的大多数调用的基础:
private void SearchDirectory(DirectoryInfo startDirectory,
string pattern,
Action<FileInfo> act)
{
foreach (var file in startDirectory.GetFiles(pattern))
act(file);
foreach (var directory in startDirectory.GetDirectories())
SearchDirectory(directory, pattern, act);
}
private List<FileInfo> SearchDirectory(DirectoryInfo startDirectory,
string pattern,
Func<FileInfo, bool> isWanted)
{
var lst = new List<FileInfo>();
SearchDirectory(startDirectory,
pattern,
(fi) => { if (isWanted(fi)) lst.Add(fi); });
return lst;
}
然后,您可以使用列出的其他解决方案来编写一个IsHidden函数,该函数采用单个FileInfo,如果是,则返回true:
private bool IsHiddenDirectory(DirectoryInfo d) {
if (d == null) return false;
if (d.Attributes.HasFlag(FileAttributes.Hidden))) return true;
if (d.Parent == null) return false;
return IsHiddenDirectory(d.Parent);
}
private bool IsHidden(FileInfo fi) {
if ((fi.Attributes & FileAttributes.Hidden) != 0) return true;
// If you're worried about parent directories hidden:
return IsHiddenDirectory(fi.Directory);
// otherwise:
return false;
}
然后,我可以很容易地用另一种方法调用它:
var files = SearchDirectory(new DirectoryInfo("C:\temp\"),
"*.xml",
(fi) => { return !IsHidden(fi); );
static bool IsHidden(string p)
{
return p.Contains("Hidden");
}
DirectoryInfo directory = new DirectoryInfo(@"C:\temp");
FileInfo[] files = directory.GetFiles();
var filtered = files.Where(f => !IsHidden(File.GetAttributes(f).ToString()));
foreach (var f in filtered)
{
Debug.WriteLine(f);
}
脚步:
创建在字符串包含“ Hidden”时返回true的布尔值---- static bool IsHidden(string p){return p.Contains("Hidden");}
获取目录信息---- DirectoryInfo directory = new DirectoryInfo(@"C:\temp");
从目录中获取文件信息数组---- FileInfo[] files = directory.GetFiles();
获取文件信息属性并从文件信息数组转换为字符串,并检查其是否包含“隐藏” ----
var filtered = files.Where(f=>!IsHidden(File.GetAttributes(f).ToString()));