Folder Recursion with C#

by Richard Carr, published at http://www.blackwasp.co.uk/FolderRecursion.aspx

Some applications must read the folder structure beneath an existing folder or for an entire disk or attached device. The standard method in the Directory class can cause problems when used in this way. An alternative is to recursively read the folders.

Reading Folders

It is common to wish to read the entire folder structure of a disk when you are creating software that works with the file system. For example, you may wish to populate a TreeView control with the complete list of directories, or you might read the folders in order to compare them with another directory or with a backup copy.

The Directory class, which is a standard type within the .NET framework, includes a method, named GetDirectories, that allows you to read the folders within a given path, returning their names in a string array. You can use further methods of the Directory and File classes to work with the folders and their contents. An example of the GetDirectories method is shown below. This returns a list of folder names that can be found in the root of the C: drive.

NB: To run this code you need to reference the System.IO namespace so add the directive, "using System.IO;" to your code.

string[] folders = Directory.GetDirectories(@"c:\");

To instruct the method to work recursively, reading the folders, their subfolders and directories beneath these until the folder structure is exhausted, you can add the AllDirectoriessearch option, as shown below:

string[] folders = Directory.GetDirectories(@"c:\", "*", SearchOption.AllDirectories);

Unfortunately, this has problems. Key amongst these is that some of the folders that you attempt to read could be configured so that the current user may not access them. Rather than ignoring folders to which you have restricted access, the method throws anUnauthorizedAccessException. However, we can circumvent this problem by creating our own recursive folder search code.

Folder Recursion

Let‘s start with some simple folder recursion code that recreates the flawed functionality of the GetDirectories method. We‘ll create it within a console application and show its activity by outputting folder name as they are examined. In a real application you could build and return a list or array, or use an iterator to return the values as they are required, thus avoiding the delay caused by reading large folder structures ahead of the time they are needed.

The code below shows the basic recursive method. The Main method callsShowAllFoldersUnder, passing in the starting path. In this case we are going to display all folders starting from the root of the C: drive.

ShowAllFoldersUnder does the real work. When this method is called it uses the basic version of GetDirectories to obtain the folder list for directories immediately within the provided path. It then loops through these folders, first displaying the name, then calling itself, passing the folder name, to look one level deeper. This recursive nature causes all folders to be examined, unless an exception is thrown.

static void Main(string[] args)
{
    Console.WriteLine(@"c:\");
    ShowAllFoldersUnder(@"c:\", 0);
}

private static void ShowAllFoldersUnder(string path, int indent)
{
    foreach (string folder in Directory.GetDirectories(path))
    {
        Console.WriteLine("{0}{1}", new string(‘ ‘, indent), Path.GetFileName(folder));
        ShowAllFoldersUnder(folder, indent + 2);
    }
}

To avoid UnauthorizedAccessExceptions stopping the execution, we need to add a try / catch block around the foreach loop. We can use this to catch only that type of exception and ignore it. This means that the folders to which the user does not have access will not be displayed. The updated ShowAllFolders code is as follows.

private static void ShowAllFoldersUnder(string path, int indent)
{
    try
    {
        foreach (string folder in Directory.GetDirectories(path))
        {
            Console.WriteLine("{0}{1}", new string(‘ ‘, indent), Path.GetFileName(folder));
            ShowAllFoldersUnder(folder, indent + 2);
        }
    }
    catch (UnauthorizedAccessException) { }
}

Reparse Points

Something else that we must deal with is reparse points, or junction points. Most disks used by Windows operating systems are formatted using the New Technology File System, or NTFS. This allows disks to be mounted in interesting ways. In addition to the usual assignment of drive letters, such as C:, disks can be mounted within folders. This means that when you use Windows Explorer to browse to the C:\OtherDisk folder, you may be seeing the contents of another disk or partition altogether.

Junction points generate a problem when recursively scanning folders; drives can be mounted in such a way as to create infinite directory structures. For example, the disk containing your C: drive could be mounted within a folder named, "C:\Infinite". If you looked inside this folder you would find everything that is in the root of C:, including the "Infinite" folder. You could continue to drill down into that folder, each time seeing the same subfolders and files.

To avoid infinite loops, we need to check that a folder is not a junction point. We can do this by reading each folder‘s attributes and checking if it is a reparse point. To get the attributes we use the File.GetAttributes method, which returns an enumeration that represents a bit field. We can then use the bitwise AND operator to check for the existence of the ReparsePointflag.

Using this information we can create the final version of ShowAllFoldersUnder, as follows:

private static void ShowAllFoldersUnder(string path, int indent)
{
    try
    {
        if ((File.GetAttributes(path) & FileAttributes.ReparsePoint)
            != FileAttributes.ReparsePoint)
        {
            foreach (string folder in Directory.GetDirectories(path))
            {
                Console.WriteLine(
                    "{0}{1}", new string(‘ ‘, indent), Path.GetFileName(folder));
                ShowAllFoldersUnder(folder, indent + 2);
            }
        }
    }
    catch (UnauthorizedAccessException) { }
}
时间: 2024-10-05 08:46:19

Folder Recursion with C#的相关文章

Visual Basic 函数速查

Calendar 常数 可在代码中的任何地方用下列常数代替实际值: 常数 值 描述 vbCalGreg 0 指出使用的是阳历. vbCalHijri 1 指出使用的是伊斯兰历法. Color 常数 可在代码中的任何地方用下列常数代替实际值: 常数 值 描述 vbBlack 0x0 黑色 vbRed 0xFF 红色 vbGreen 0xFF00 绿色 vbYellow 0xFFFF 黄色 vbBlue 0xFF0000 蓝色 vbMagenta 0xFF00FF 紫红色 vbCyan 0xFFFF

在eclipse下,package,source folder,folder的区别

在eclipse下,package,source folder,folder都是文件夹. 它们的区别如下:package:当你在建立一个package时,它自动建立到source folder下,也只能建立在这个目录之下. source folder:存放java源代码的文件夹,当然也包括一些package文件夹,还可以包含其他文件.项目构建后,source folder里面的java自动编译成class文件到相应的bin文件夹中,其他文件也会移到到相应的目录下. folder:里面可以放入任何

the tomcat installation directory is not valid. It is missing excepted file or folder

问题描述 : the tomcat installation directory is not valid 原因 : 我在上一页没有选择apache tomcat 7.0,因为eclipse版本太低,只有到6.0的server供选择 所以这边就算把Name改成7.0,还是配置不了 解决方案: 安装更高版本的eclipse the tomcat installation directory is not valid. It is missing excepted file or folder,布布

Eclipse中的创建maven项目,无法添加src/main/java等source folder

通过Eclipse创建Java Web项目,目录结构如下: 默认是只有src/main/resources 这个source folder 按照maven目录结构,还需要src/main/java ;  src/test/java; src/test/resources 等 在eclipse中创建这些source folder时,会出现下面的情况: 解决如下: 一. 打开Eclipse的Navigator目录,依次创建missing的 source folder即可. 不知道怎么打开的,可以看我

Python的最大递归深度错误 “maximum recursion depth exceeded while calling a Python object”

今天在写爬虫的时候,发现了一个诡异的事情,使用str方法强制转换一个BeautifulSoup对象成字符串的时候报错了,提示是"maximum recursion depth exceeded while calling a Python object",意思大致是"当调用该对象超过最大递归深度" 报错如下:   Traceback (most recent call last):   File "<stdin>", line 1, 

Scala Learning(3): Tail Recursion定义

关于尾递归 ,使用Scala的两个例子展示尾递归的定义和简单实现. 例子比较 求最大公约数的函数 def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) 计算的展开是尾递归的, gcd(14, 21) -> if (21 == 0) 14 else gcd(21, 14 % 21) -> if (false) 14 else gcd(21, 14 % 21) -> gcd(21, 14 % 21) -> gcd

递归和迭代(Recursion and Iteration)

递归 特点:简而言之,递归就是应用程序调用自身.所以,存在预期收敛,才能使用递归(因为不能无限期递归调用下去). 优点:程序看着比较简单,比较容易实现. 缺点:递归要占用额外的栈空间,如果递归的深度比较大,那么占用的栈比较多,而且调用函数的时间也比较多,时空性都不好. 所以选择递归要考虑好处和缺点之间的权衡. 迭代 特点:通过步号寻找需要的信息,经典的例子比如C++中的for循环语句(迭代遍历程序). 优点:开销只因循环的增加而相应增加,没有额外的空间开销和时间开销. 缺点:编写复杂问题时可能程

Recursion

Recursion It is legal for one function to call another; it is also legal for a function to call itself. It may not be obvious why what is a good thing, but it turns out to be one of the most magical things a program can do. For example: If a recursio

Error writing temporary file. Make sure your temp folder is valid

NSIS Error:Error writing temporary file. Make sure your temp folder is valid的解决 老婆用了自己的WIN7系统一段时间之后,一直说系统越来越慢,让我帮她重装系统.好吧,那就重装命令呗.幸好我当时给她安装完WIN7之后用GHOST备份了一下.关机,GHOST,等待6分钟...OK,安装完毕.接着就是安装必备软件了,什么360啊,QQ啊,搜狗输入法啊.但是问题来了,不管我安装什么软件,总是报“NSIS Error: "Err