【问题标题】:Delete all folders and subdirectories that doesn't have a file of certain extension删除所有没有特定扩展名文件的文件夹和子目录
【发布时间】:2016-03-20 05:41:30
【问题描述】:

我正在使用这个解决方案来删除某个路径下的所有空文件夹和子目录:

static void Main(string[] args)
{
    processDirectory(@"c:\temp");
}

private static void processDirectory(string startLocation)
{
    foreach (var directory in Directory.GetDirectories(startLocation))
    {
        processDirectory(directory);
        if (Directory.GetFiles(directory).Length == 0 && 
            Directory.GetDirectories(directory).Length == 0)
        {
            Directory.Delete(directory, false);
        }
    }
}

完美运行。但我想删除所有空文件夹以及不为空但也不包含带有.dvr 扩展名的文件的文件夹。

例如,我的文件夹有文件:

一个日志

b.log

c.dvr

d.dat

所以这个文件夹不能被删除,因为它包含一个带有 dvr 扩展名的文件。

如何过滤它? (我正在使用 GTK#,但我相信 C# 代码会起作用,因为这个解决方案是 C# 代码)

【问题讨论】:

    标签: c# directory gtk#


    【解决方案1】:

    不幸的是,错误处理是非常基于 IO 操作的异常。如果目录不为空,Directory.Delete 会引发 IOException。所以你必须手动删除文件:

    private static bool processDirectory(string startLocation)
    {
        bool result = true;
        foreach (var directory in Directory.GetDirectories(startLocation))
        {
            bool directoryResult = processDirectory(directory);
            result &= directoryResult;
    
            if (Directory.GetFiles(directory, "*.dvr").Any())
            {
                 result = false;
                 continue;
            }
    
            foreach(var file in Directory.GetFiles(directory))
            {
                try
                {
                   File.Delete(file);
                }
                catch(IOException)
                {
                   // error handling
                   result = directoryResult = false;
                }
            }
    
            if (!directoryResult) continue;
            try
            {
                Directory.Delete(directory, false);
            }
            catch(IOException)
            {
                // error handling
                result = false;
            }
        }
    
        return result;
    }
    

    【讨论】:

    • 您的解决方案经过一些更改后效果最佳。 GTK# 不接受任何()。所以我不得不改用长度,它工作正常;D
    【解决方案2】:

    我会使用Directory.EnumerateFiles 来查看目录是否包含您要查找的文件。将您的代码更改为:

    static void Main(string[] args)
    {
        processDirectory(@"c:\temp");
    }
    
    private static void processDirectory(string startLocation)
    {
        foreach (var directory in Directory.GetDirectories(startLocation))
        {
            processDirectory(directory);
            if (Directory.GetDirectories(directory).Length == 0  ||
                Directory.EnumerateFiles(directory, "*.dvr").Length == 0
                )
            {
                Directory.Delete(directory, false);
            }
        }
    }
    

    【讨论】:

    • 你应该知道Directory.Delete如果目录包含文件会抛出一个IOException,所以你必须手动删除它们。
    • 这适用于 .net 4.5 或 4.6,我认为 GTK# 是 .net 2.0,有什么解决方案吗?
    • 查看我对 .NET 2.0 示例的回答。如果您排除 Linq-parts,@RenéVogt 的答案也将起作用。
    • 您可以使用.Any() 而不是Length 作为EnumerateFiles,以避免枚举所有文件。
    • @MicroVirus Length 实际上甚至不是EnumerateFiles 的有效属性,因为它返回IEnumerable<string>。所以使用Any() 将是最好的方法。但是,如果; Length 是一个有效的属性(即它返回一个string[])然后它会“更快”,因为它只是一个带有支持字段的属性。如果您将LengthCount() 混淆,那么Count() 将比Any() 更快但前提是它返回具有Count 属性的IList<string>
    【解决方案3】:

    Avitus answer 是正确的,但是由于您需要它在 .NET 2.0 中工作,所以您不能使用 EnumerateFiles 方法,但是 GetFiles 可以很好地完成工作。但需要更多代码。

    示例:

    static void Main(string[] args)
    {
        processDirectory(@"c:\temp");
    }
    
    private static void processDirectory(string startLocation)
    {
        foreach (var directory in Directory.GetDirectories(startLocation))
        {
            processDirectory(directory);
    
            if (Directory.GetDirectories(directory).Length == 0))
            {
                bool delete = false;
    
                var files = Directory.GetFiles(directory);
                // This will delete the directory if it contains a file with the Extension
                // of .dvr, regardless if there are other files in there. Might be something you want to change.
                for (int i = 0; i < files.Length && !delete; i++)
                {
                    delete = files[i].Extension.Equals(".dvr", StringComparison.OrdinalIgnoreCase);
                }
    
                if (delete)
                {
                    // Recursive must be set to true in order to
                    // delete files and sub-directories in the folder.
                    // This folder will not have any sub-directories
                    // so it's only used to delete the files.
                    Directory.Delete(directory, /*recursive*/ true);
                }
            }
        }
    }
    

    本着更少代码的精神,您可以在for 循环中移动Directory.Delete 方法调用,如果需要,然后中断循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 2014-07-25
      • 1970-01-01
      • 2012-11-29
      相关资源
      最近更新 更多