How to delete files in the relocation folder tree

I'm not sure if I'm doing this correctly, or if my logic is correct.

I am trying to demolish a folder structure by deleting files older than a certain number of days, this part I have implemented correctly deletes empty folders.

Can all this be done in one cycle?
Where can I delete the folder?

I want to delete empty folders up to 3 or 4 levels.

    private static void TraverseTree(System.IO.DirectoryInfo folder, double days)
    {
        Stack<string> dirs = new Stack<string>();

        if (!folder.Exists)
            throw new ArgumentException();

        dirs.Push(folder.FullName);

        while (dirs.Count > 0)
        {
            string currentDir = dirs.Pop();
            string[] subDirs;
            try
            {
                subDirs = System.IO.Directory.GetDirectories(currentDir);
            }
            // An UnauthorizedAccessException exception will be thrown if we do not have
            // discovery permission on a folder or file. It may or may not be acceptable 
            // to ignore the exception and continue enumerating the remaining files and 
            // folders. It is also possible (but unlikely) that a DirectoryNotFound exception 
            // will be raised. This will happen if currentDir has been deleted by
            // another application or thread after our call to Directory.Exists. The 
            // choice of which exceptions to catch depends entirely on the specific task 
            // you are intending to perform and also on how much you know with certainty 
            // about the systems on which this code will run.
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }

            string[] files = null;
            try
            {
                files = System.IO.Directory.GetFiles(currentDir);
            }
            catch (UnauthorizedAccessException e)
            {

                Console.WriteLine(e.Message);
                continue;
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }

            // Perform the required action on each file here.
            // Modify this block to perform your required task.
            foreach (string file in files)
            {
                try
                {
                    // Perform whatever action is required in your scenario.
                    System.IO.FileInfo fi = new System.IO.FileInfo(file);
                    Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);

                    // Delete old files
                    if (fi.LastWriteTime < DateTime.Now.AddDays(-days))
                        fi.Delete();
                }
                catch (System.IO.FileNotFoundException e)
                {
                    // If file was deleted by a separate application
                    //  or thread since the call to TraverseTree()
                    // then just continue.
                    Console.WriteLine(e.Message);
                    continue;
                }
            }

            // Push the subdirectories onto the stack for traversal.
            // This could also be done before handing the files.
            foreach (string str in subDirs)
                dirs.Push(str);
        }
    }

      

Code from MSDN .

+2


source to share


5 answers


A recursive approach is likely to be cleaner.



private static void DeleteOldFilesAndFolders(string path)
{
    foreach (string directory in System.IO.Directory.GetDirectories(path))
    {
        DeleteOldFilesAndFolders(directory);

        // If the directory is empty and old, delete it here.
    }

    foreach (string file in System.IO.Directory.GetFiles(path))
    {
        // Check the file age and delete it if it old.
    }
}

      

+5


source


Something I noticed about your code is that dozens of lines of "mechanism" for walking through the tree structure completely overwhelm the two lines of code that actually get the job done. This makes this code difficult to read, understand, modify, debug, and save.

Here's what I would do instead.

There are only three high-level operations in your program: (1) get all files, (2) filter to find the ones to delete, (3) delete each file. So write a program that does each of them in one statement.

For the first operation, I would separate the above mechanism into my own function: a function that implements, say, IEnumerable, and whatever it does, it continues to output information about files. He does nothing with them; its sole purpose is to store information about files.



Once you have this mechanism, you can start writing queries on top of this sequence to perform the second operation. The third operation then follows directly from the second.

In short, the main line of your program should look something like this:

var allFiles = TraverseFolder(folder);
var filesToDelete = from file in allFiles where IsOld(file) select file;
foreach(var fileToDelete in filesToDelete) Delete(fileToDelete);

      

It is clear?

+3


source


Here's almost the same question:

How do I delete all files and folders in a directory?

This is deletion by name, but you can check other properties.

0


source


Below is a more general solution to the problem that gives you a filesystem walker implemented non-recursively as IEnumerable.

for which your solution can be implemented as:

List<string> directoriesToDelete = new List<string>();
DirectoryWalker walker = new DirectoryWalker(@"C:\pathToSource\src",
    dir => {
        if (Directory.GetFileSystemEntries(dir).Length == 0) {
            directoriesToDelete.Add(dir);
            return false;
        }
        return true;
    },
    file => {
        if (FileIsTooOld(file)) {
            return true;
        }
        return false;
    }
    );
foreach (string file in walker)
    File.Delete(file);
foreach (string dir in directoriesToDelete)
    Directory.Delete(dir);

      

0


source


I improved John 's solution by injecting missing code, error handling and validation:

/* Given a directory path and a datetime,
 * recursively delete all files and directories contained in such directory
 * (given directory included) that are younger than the given date.
 */
private bool DeleteDirectoryTree(string dir, DateTime keepFilesYoungerThan)
{
    //checks
    if (String.IsNullOrEmpty(dir) || !Directory.Exists(dir))
        return false;

    //recurse on children directories
    foreach (string childDir in Directory.GetDirectories(dir))
        DeleteDirectoryTree(childDir, keepFilesYoungerThan);

    //loop on children files
    foreach (string file in Directory.GetFiles(dir))
    {
        //calculate file datetime
        DateTime fileDT = new DateTime(Math.Max(File.GetCreationTime(file).Ticks, File.GetLastWriteTime(file).Ticks));
        //if file is old, delete it
        if (fileDT <= keepFilesYoungerThan)
            try
            {
                File.Delete(file);
                Log("Deleted file " + file);
            }
            catch (Exception e)
            {
                LogError("Could not delete file " + file + ", cause: " + e.Message);
            }
    }

    //if this directory is empty, delete it
    if (!Directory.EnumerateFileSystemEntries(dir).Any())
        try
        {
            Directory.Delete(dir);
            Log("Deleted directory " + dir);
        }
        catch (Exception e)
        {
            LogError("Could not delete directory " + dir + ", cause: " + e.Message);
        }

    return true;
}

      

0


source







All Articles