0

I am trying to delete all folders older that one day from a path in java using the following code:

public static void removeDirectory(File dir) {

    long purgeTime = System.currentTimeMillis() - (1 * 24 * 60 * 60 * 1000);

    if (dir.isDirectory()) {
        File[] files = dir.listFiles();

        for (File aFile : files) {
            if (aFile.lastModified() < purgeTime) {
                removeDirectory(aFile);
            }
        }
        dir.delete();
    } else {
        dir.delete();
    }
}

public static void createBackupFS(java.awt.event.ActionEvent evt) {

    File directory = new File(pathsavefsbackup.getText());
    removeDirectory(directory);
}

The only thing that is happening is that the old files are modified with the current time. Mention that the root folder has a folder in it which has files inside it.

Path structure:

root folder - last modified (2 days ago) -> test folder last modified (2 days ago) -> file1.jpg (last modified 3 days ago), file2.txt (last modified 4 days ago).

Could any one help me?

Thank you!

Bogdan
  • 155
  • 2
  • 3
  • 10
  • Possible duplicate of [Delete files older than x days](https://stackoverflow.com/questions/15042855/delete-files-older-than-x-days) – D.B. Jun 18 '18 at 16:19
  • 1
    It's not duplicate , I have checked before. The problem is related to the fact that the root folder has a folder in it which has also files in it. – Bogdan Jun 18 '18 at 16:22
  • I cannot reproduce a problem. Can you update your question with the folder structure you have with last modified dates shown against each file/folder? – Jaroslaw Pawlak Jun 18 '18 at 16:24
  • 2
    Is there a particular reason you use the old outdated File API instead of NIO (`Files`, `Paths`, `Path`)? Also note that your way of determining a *day* does not work correct in presence of practical difficulties like timezones, daylight saving, leap years, leap seconds, ... You can use the modern Time API for such stuff (`LocalDateTime`, `LocalDate`, `LocalTime`). – Zabuzard Jun 18 '18 at 16:27
  • 1
    Updated the structure path. No there is no reason, is the only way I thought can be done. – Bogdan Jun 18 '18 at 16:29
  • https://stackoverflow.com/questions/50742815/java-delete-files-older-than-n-days-with-path-filename-and-n-days-as-variable/50744248#50744248 – SedJ601 Jun 18 '18 at 16:31

2 Answers2

1

the for loop is looping through every file in the given folder

for (File aFile : files)

so all you have to do is to check if the current file is older than 24 hour or not if it is delete it otherwise not. You do not need to overcomplicate the code here is the modified version of your code.

The below code delete any folder/file in given directory older than 1 Day

   public static void removeDirectory(File dir) {
        boolean delSource = false;
        long purgeTime = System.currentTimeMillis() - (10 * 1000);
        if (dir.lastModified()< purgeTime) delSource = true;
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            for (File aFile : files) {
                if (aFile.lastModified() < purgeTime) {
                    aFile.delete();
                }
            }
        }
        if(delSource) dir.delete();
    }

    public static void createBackupFS() {

        File directory = new File("F:\\document\\eclipse\\JavaAZ\\src\\Delete");
        removeDirectory(directory);
    }

PS: if there are files inside files and so on you have to use recursion for that

Recursive Solution for all files and folder

public static void removeDirectory(File dir) {
        long purgeTime = System.currentTimeMillis() - (1 * 24 * 60 * 60 * 1000);

        if(dir.isDirectory() == false && dir.lastModified() < purgeTime) dir.delete();
        else if (dir.isDirectory() == true && dir.lastModified() < purgeTime) recursiveDelete(dir);
        else if(dir.isDirectory()){
             File[] files = dir.listFiles();
             for (File aFile : files)
                 removeDirectory(aFile);
        }
    }

    public static void createBackupFS() {

        File directory = new File("F:\\downloads\\Compressed\\backup");
        removeDirectory(directory);
    }
     public static void recursiveDelete(File file) {
            if (!file.exists())
                return;

            if (file.isDirectory()) {
                for (File f : file.listFiles()) {
                    recursiveDelete(f);
                }
            }
            file.delete();
        }
Sundeep
  • 452
  • 2
  • 12
  • 3
    Is there a particular reason you use the old outdated File API instead of NIO (`Files`, `Paths`, `Path`)? Also note that your way of determining a day does not work correct in presence of practice difficulties like timezones, daylight saving, leap years, leap seconds, ... You can use the modern Time API for such stuff (`LocalDateTime`, `LocalDate`, `LocalTime`). Also, can you explain the changes or why the code solves the problem? Code-only answers often are not that helpful. – Zabuzard Jun 18 '18 at 17:07
  • because i don't want to confuse the questioner with new code – Sundeep Jun 18 '18 at 17:08
  • 1
    Fine. Nonetheless I miss the explanation or highlights of changes for a `+1`. And in my opinion it would be better to show both, the fix **and** the solution using non-legacy and best-practice code, working in all situations. Else your answer is of little use for future readers (see [answer]). – Zabuzard Jun 18 '18 at 17:11
  • 1
    Actually I recently been active on SO and I'm trying to understand the best practice which is beneficial for everyone. Everyone's feedback is making me better. So +1 to you :) – Sundeep Jun 18 '18 at 17:14
  • It doesn't delete the folder with its contents, just set the date modified to actual time. – Bogdan Jun 18 '18 at 17:17
  • @Bogdan do you want to delete the source folder too like in the above case "Delete" folder – Sundeep Jun 18 '18 at 17:19
  • Yes I want to delete the parent directory if is older than one day and all its contents. – Bogdan Jun 18 '18 at 17:21
  • sorry for late code have been updated now it will work with your requirement – Sundeep Jun 18 '18 at 17:35
  • Still doesn't delete the folder just modify the date modified to current time. I have the root folder which has a folder in it which has some files, I need to delete the root folder with its folder which contains some files. – Bogdan Jun 18 '18 at 17:56
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173352/discussion-between-sundeep-and-bogdan). – Sundeep Jun 18 '18 at 18:01
1

Java NIO2 (Path, Files, FileVisitor)

I'm using 2 classes that implements FileVisitor interface. The first one detects all folders/subfolders that has been modified before X period of time. The second one deletes all folders stored by the first class

Files.walkFileTree(Path, FileVisitor<Class>) is used to walk through directories. All classes inside one (you can extract FileVisitorFolders and FileVisitorDeleteFolders to class file

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.Period;
import java.util.ArrayList;

public class Main {


    private static class FileVisitorFolders implements FileVisitor<Path> {

        private Instant beforePeriodOfTime;
        private ArrayList<Path> directories = new ArrayList<>(10);

        public FileVisitorFolders(Period time) {
            beforePeriodOfTime = Instant.now().minus(time);
        }

        public ArrayList<Path> getDirectories() {
            return directories;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            var lastModifiedTime = Files.getLastModifiedTime(dir, LinkOption.NOFOLLOW_LINKS);
            if (lastModifiedTime.toInstant().isBefore(beforePeriodOfTime)) {
                directories.add(dir);
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            return FileVisitResult.CONTINUE;
        }
    }

    private static class FileVisitorDeleteFolders implements FileVisitor<Path> {


        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    }

    public static void main(String[] args) {
        var fileVisitorFolders = new FileVisitorFolders(Period.ofDays(1));
        var fileVisitorDeleteFolder = new FileVisitorDeleteFolders();
        try {
            Files.walkFileTree(Paths.get("testFolder"), fileVisitorFolders);
            for (Path dir : fileVisitorFolders.getDirectories()) {
                System.out.printf("Deleting: %s\n", dir.toAbsolutePath().toString());
                Files.walkFileTree(dir, fileVisitorDeleteFolder);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

How it works?

Here we have the next directories: (Note: Today is 2018-06-18)

tree -D testFolder/
testFolder/
├── [Jun 17  5:00]  a
├── [Jun 18 18:06]  b
├── [Jun 15  5:00]  c
│   ├── [Jun 18 18:06]  e
│   └── [Jun 18 18:06]  hi
└── [Jun 18 17:30]  e

5 directories, 1 file

The folders a has been modified 1 day ago and the folder c has been modified 3 days ago. The folder a is empty and the folder c have a subfolder e and a file hi

The main method is:

 public static void main(String[] args) {
        var fileVisitorFolders = new FileVisitorFolders(Period.ofDays(1));
        var fileVisitorDeleteFolder = new FileVisitorDeleteFolders();
        try {
            Files.walkFileTree(Paths.get("testFolder"), fileVisitorFolders);
            for (Path dir : fileVisitorFolders.getDirectories()) {
                System.out.printf("Deleting: %s\n", dir.toAbsolutePath().toString());
                Files.walkFileTree(dir, fileVisitorDeleteFolder);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  1. Check recursively all subfolders of testFolder and save a Path of every folder than has been modified before this period of time: Period.ofDays(1)
  2. Delete (recursively) all folders saved previously (Paths)

Output:

Deleting: /root/IdeaProjects/DeleteFolder/testFolder/a
Deleting: /root/IdeaProjects/DeleteFolder/testFolder/c

Process finished with exit code 0

Now we have:

tree -D testFolder/
testFolder/
├── [Jun 18 18:06]  b
└── [Jun 18 17:30]  e

2 directories, 0 files

Note: Before use it, test it commenting the line: //Files.walkFileTree(dir, fileVisitorDeleteFolder); To change the date of last modified file/folder (on Linux) you can use the command touch like:

touch -m -t 201806150700 folderName/fileName

-m -> last modified time

-t -> time

If you want less code, use extends SimpleFileVisitor instead implements FileVisitor and only implements the necessary methods (omit all empty methods)

If you are using Java before 1.10 replace var with the instance type.


Important Be carefull with this code. If the parent folder (in this case: testFolder) has not been modified in the last period of time it will be deleted too.

To avoid this situation you can modify the main method:

  public static void main(String[] args) {
        var parent = Paths.get("testFolder");
        var fileVisitorFolders = new FileVisitorFolders(Period.ofDays(1));
        var fileVisitorDeleteFolder = new FileVisitorDeleteFolders();
        try {
            Files.walkFileTree(parent, fileVisitorFolders);
            var foldersToDelete = fileVisitorFolder.getDirectories();
            foldersToDelete.remove(parent);
            for (Path dir : foldersToDelete) {
                System.out.printf("Deleting: %s\n", dir.toAbsolutePath().toString());
                Files.walkFileTree(dir, fileVisitorDeleteFolder);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
VasileM
  • 606
  • 7
  • 13