Delete files older than x days
Asked Answered
I

15

47

How can I find out when a file was created using java, as I wish to delete files older than a certain time period, currently I am deleting all files in a directory, but this is not ideal:

public void DeleteFiles() {
    File file = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/");
    System.out.println("Called deleteFiles");
    DeleteFiles(file);
    File file2 = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/");
    DeleteFilesNonPdf(file2);
}

public void DeleteFiles(File file) {
    System.out.println("Now will search folders and delete files,");
    if (file.isDirectory()) {
        for (File f : file.listFiles()) {
            DeleteFiles(f);
        }
    } else {
        file.delete();
    }
}

Above is my current code, I am trying now to add an if statement in that will only delete files older than say a week.

EDIT:

@ViewScoped
@ManagedBean
public class Delete {

    public void DeleteFiles() {
        File file = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/");
        System.out.println("Called deleteFiles");
        DeleteFiles(file);
        File file2 = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/");
        DeleteFilesNonPdf(file2);
    }

    public void DeleteFiles(File file) {
        System.out.println("Now will search folders and delete files,");
        if (file.isDirectory()) {
            System.out.println("Date Modified : " + file.lastModified());
            for (File f : file.listFiles()) {
                DeleteFiles(f);
            }
        } else {
            file.delete();
        }
    }

Adding a loop now.

EDIT

I have noticed while testing the code above I get the last modified in :

INFO: Date Modified : 1361635382096

How should I code the if loop to say if it is older than 7 days delete it when it is in the above format?

Io answered 23/2, 2013 at 16:39 Comment(0)
S
50

You can use File.lastModified() to get the last modified time of a file/directory.

Can be used like this:

long diff = new Date().getTime() - file.lastModified();

if (diff > x * 24 * 60 * 60 * 1000) {
    file.delete();
}

Which deletes files older than x (an int) days.

Simonize answered 23/2, 2013 at 16:41 Comment(5)
it will give the last modified time not the file creation time.Monomorphic
Thats fine, no modificatins can be done to the file once it is created no one can edit it :)Io
:D That's really simple. i'm writing the ans for file creation time. ;)Monomorphic
Thanks ! :) am testing it atm but so far looks perfect !Io
With X == 25 you get int overflow. 25 * 24 * 60 * 60 * 1000L is more robustLactobacillus
N
33

Commons IO has built-in support for filtering files by age with its AgeFileFilter. Your DeleteFiles could just look like this:

import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.AgeFileFilter;
import static org.apache.commons.io.filefilter.TrueFileFilter.TRUE;

// a Date defined somewhere for the cutoff date
Date thresholdDate = <the oldest age you want to keep>;

public void DeleteFiles(File file) {
    Iterator<File> filesToDelete =
        FileUtils.iterateFiles(file, new AgeFileFilter(thresholdDate), TRUE);
    for (File aFile : filesToDelete) {
        aFile.delete();
    }
}

Update: To use the value as given in your edit, define the thresholdDate as:

Date tresholdDate = new Date(1361635382096L);
Nanananak answered 23/2, 2013 at 23:11 Comment(4)
Is there any way you can combine the AgeFileFilter with another filter, such as the NameFileFilter?Embryologist
@Embryologist see AndFileFilter and OrFileFilterOtoole
Parameters: iterateFiles(File directory, IOFileFilter fileFilter, IOFileFilter dirFilter), dirfilter is optional (can be null)Rumpus
Example does not compile, cannot iterate over Iterator Probably want to use listFiles?Wulfe
B
17

Using Apache utils is probably the easiest. Here is the simplest solution I could come up with.

public void deleteOldFiles() {
    Date oldestAllowedFileDate = DateUtils.addDays(new Date(), -3); //minus days from current date
    File targetDir = new File("C:\\TEMP\\archive\\");
    Iterator<File> filesToDelete = FileUtils.iterateFiles(targetDir, new AgeFileFilter(oldestAllowedFileDate), null);
    //if deleting subdirs, replace null above with TrueFileFilter.INSTANCE
    while (filesToDelete.hasNext()) {
        FileUtils.deleteQuietly(filesToDelete.next());
    }  //I don't want an exception if a file is not deleted. Otherwise use filesToDelete.next().delete() in a try/catch
}
Bernadettebernadina answered 4/2, 2015 at 19:57 Comment(3)
It's also worth noting that you can use milliseconds to create an AgeFileFilter like this new AgeFileFilter(System.currentTimeMillis() - AGE_LIMIT_MILLIS) where AGE_LIMIT_MILLIS could be say 24*60*60*1000L for 24 hours.Revocation
@Bernadettebernadina Does this have any impact like out of memory exception if i use it for the directory having 2 or 3 million records?Hernia
@Diwa Yes, I am guessing you could run into memory issues if you had millions of files. FileUtils creates a java.util.LinkedList, and then returns the iterator of that list.Bernadettebernadina
S
14

Example using Java 8's Time API

LocalDate today = LocalDate.now();
LocalDate eailer = today.minusDays(30);
    
Date threshold = Date.from(eailer.atStartOfDay(ZoneId.systemDefault()).toInstant());
AgeFileFilter filter = new AgeFileFilter(threshold);
    
File path = new File("...");
File[] oldFolders = FileFilterUtils.filter(filter, path);
    
for (File folder : oldFolders) {
    System.out.println(folder);
}
Southwesterly answered 9/9, 2015 at 1:51 Comment(1)
To be clear, AgeFileFilter is from Apache Commons IO, not from the Java 8 Time API.Kaleidoscope
N
13

Using lambdas (Java 8+)

Non recursive option to delete all files in current folder that are older than N days (ignores sub folders):

public static void deleteFilesOlderThanNDays(int days, String dirPath) throws IOException {
    long cutOff = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000);
    Files.list(Paths.get(dirPath))
    .filter(path -> {
        try {
            return Files.isRegularFile(path) && Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS) < cutOff;
        } catch (IOException ex) {
            // log here and move on
            return false;
        }
    })
    .forEach(path -> {
        try {
            Files.delete(path);
        } catch (IOException ex) {
            // log here and move on
        }
    });
}

Recursive option, that traverses sub-folders and deletes all files that are older than N days:

public static void recursiveDeleteFilesOlderThanNDays(int days, String dirPath) throws IOException {
    long cutOff = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000);
    Files.list(Paths.get(dirPath))
    .forEach(path -> {
        if (Files.isDirectory(path)) {
            try {
                recursiveDeleteFilesOlderThanNDays(days, path.toString());
            } catch (IOException e) {
                // log here and move on
            }
        } else {
            try {
                if (Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS) < cutOff) {
                    Files.delete(path);
                }
            } catch (IOException ex) {
                // log here and move on
            }
        }
    });
}
New answered 17/10, 2017 at 13:43 Comment(0)
P
13

Here's Java 8 version using Time API. It's been tested and used in our project:

    public static int deleteFiles(final Path destination,
        final Integer daysToKeep) throws IOException {

    final Instant retentionFilePeriod = ZonedDateTime.now()
            .minusDays(daysToKeep).toInstant();

    final AtomicInteger countDeletedFiles = new AtomicInteger();
    Files.find(destination, 1,
            (path, basicFileAttrs) -> basicFileAttrs.lastModifiedTime()
                    .toInstant().isBefore(retentionFilePeriod))
            .forEach(fileToDelete -> {
                try {
                    if (!Files.isDirectory(fileToDelete)) {
                        Files.delete(fileToDelete);
                        countDeletedFiles.incrementAndGet();
                    }
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });

    return countDeletedFiles.get();
}
Pompadour answered 14/9, 2018 at 18:4 Comment(1)
I was adapting this for what I needed, and had a warning from SonarQube noting that the Files.find stream should be closed, or ideally put into a try with resources block.Podgorica
T
6

For a JDK 8 solution using both NIO file streams and JSR-310

long cut = LocalDateTime.now().minusWeeks(1).toEpochSecond(ZoneOffset.UTC);
Path path = Paths.get("/path/to/delete");
Files.list(path)
        .filter(n -> {
            try {
                return Files.getLastModifiedTime(n)
                        .to(TimeUnit.SECONDS) < cut;
            } catch (IOException ex) {
                //handle exception
                return false;
            }
        })
        .forEach(n -> {
            try {
                Files.delete(n);
            } catch (IOException ex) {
                //handle exception
            }
        });

The sucky thing here is the need for handling exceptions within each lambda. It would have been great for the API to have UncheckedIOException overloads for each IO method. With helpers to do this one could write:

public static void main(String[] args) throws IOException {
    long cut = LocalDateTime.now().minusWeeks(1).toEpochSecond(ZoneOffset.UTC);
    Path path = Paths.get("/path/to/delete");
    Files.list(path)
            .filter(n -> Files2.getLastModifiedTimeUnchecked(n)
                    .to(TimeUnit.SECONDS) < cut)
            .forEach(n -> {
                System.out.println(n);
                Files2.delete(n, (t, u)
                              -> System.err.format("Couldn't delete %s%n",
                                                   t, u.getMessage())
                );
            });
}


private static final class Files2 {

    public static FileTime getLastModifiedTimeUnchecked(Path path,
            LinkOption... options)
            throws UncheckedIOException {
        try {
            return Files.getLastModifiedTime(path, options);
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }

    public static void delete(Path path, BiConsumer<Path, Exception> e) {
        try {
            Files.delete(path);
        } catch (IOException ex) {
            e.accept(path, ex);
        }
    }

}
Thunderstruck answered 15/11, 2015 at 22:39 Comment(0)
S
6

JavaSE Canonical Solution. Delete files older than expirationPeriod days.

private void cleanUpOldFiles(String folderPath, int expirationPeriod) {
    File targetDir = new File(folderPath);
    if (!targetDir.exists()) {
        throw new RuntimeException(String.format("Log files directory '%s' " +
                "does not exist in the environment", folderPath));
    }

    File[] files = targetDir.listFiles();
    for (File file : files) {
        long diff = new Date().getTime() - file.lastModified();

        // Granularity = DAYS;
        long desiredLifespan = TimeUnit.DAYS.toMillis(expirationPeriod); 

        if (diff > desiredLifespan) {
            file.delete();
        }
    }
}

e.g. - to removed all files older than 30 days in folder "/sftp/logs" call:

cleanUpOldFiles("/sftp/logs", 30);

Spode answered 19/5, 2020 at 3:0 Comment(0)
A
4

You can get the creation date of the file using NIO, following is the way:

BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
System.out.println("creationTime: " + attrs.creationTime());

More about it can be found here : http://docs.oracle.com/javase/tutorial/essential/io/fileAttr.html

Ayrshire answered 23/2, 2013 at 16:47 Comment(1)
BasicFileAttributes is available only with java 7. You can not use it with java 6 or earlier releases.Simonize
A
3

Another approach with Apache commons-io and joda:

private void deleteOldFiles(String dir, int daysToRemainFiles) {
    Collection<File> filesToDelete = FileUtils.listFiles(new File(dir),
            new AgeFileFilter(DateTime.now().withTimeAtStartOfDay().minusDays(daysToRemainFiles).toDate()),
            TrueFileFilter.TRUE);    // include sub dirs
    for (File file : filesToDelete) {
        boolean success = FileUtils.deleteQuietly(file);
        if (!success) {
            // log...
        }
    }
}
Alli answered 31/7, 2016 at 12:59 Comment(0)
R
3

Using Java NIO Files with lambdas & Commons IO

final long time = System.currentTimeMillis();
// Only show files & directories older than 2 days
final long maxdiff = TimeUnit.DAYS.toMillis(2);

List all found files and directories:

Files.newDirectoryStream(Paths.get("."), p -> (time - p.toFile().lastModified()) < maxdiff)
.forEach(System.out::println);

Or delete found files with FileUtils:

Files.newDirectoryStream(Paths.get("."), p -> (time - p.toFile().lastModified()) < maxdiff)
.forEach(p -> FileUtils.deleteQuietly(p.toFile()));
Rhesus answered 17/1, 2018 at 15:25 Comment(1)
Would suggest using System.currentTimeMillis(), also I think it should be > .Bourbon
S
1

Here is the code to delete files which are not modified since six months & also create the log file.

package deleteFiles;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class Delete {
    public static void deleteFiles()
    {
        int numOfMonths = -6;
        String path="G:\\Files";
        File file = new File(path);
        FileHandler fh;
        Calendar sixMonthAgo = Calendar.getInstance();
        Calendar currentDate = Calendar.getInstance();
        Logger logger = Logger.getLogger("MyLog");
        sixMonthAgo.add(Calendar.MONTH, numOfMonths);
        File[] files = file.listFiles();
        ArrayList<String> arrlist = new ArrayList<String>();

        try {
            fh = new FileHandler("G:\\Files\\logFile\\MyLogForDeletedFile.log");
            logger.addHandler(fh);
            SimpleFormatter formatter = new SimpleFormatter();
            fh.setFormatter(formatter);

            for (File f:files)
            {
                if (f.isFile() && f.exists())
                {
                    Date lastModDate = new Date(f.lastModified());
                    if(lastModDate.before(sixMonthAgo.getTime()))
                    {
                        arrlist.add(f.getName());
                        f.delete();
                    }
                }
            }
            for(int i=0;i<arrlist.size();i++)
                logger.info("deleted files are ===>"+arrlist.get(i));
        }
        catch ( Exception e ){
            e.printStackTrace();
            logger.info("error is-->"+e);
        }
    }
    public static void main(String[] args)
    {
        deleteFiles();
    }
}
Saum answered 11/8, 2016 at 10:18 Comment(1)
It's more helpful to explain the parts that the OP doesn't understand, rather than providing them with a bulk of code that does approximately what they wanted. Take a look at the accepted answer here, it has much less code than yours, but more explanation and it solved the question succinctly.Daughterly
I
0

Need to point out a bug on the first solution listed, x * 24 * 60 * 60 * 1000 will max out int value if x is big. So need to cast it to long value

long diff = new Date().getTime() - file.lastModified();

if (diff > (long) x * 24 * 60 * 60 * 1000) {
    file.delete();
}
Illusive answered 7/7, 2016 at 19:4 Comment(0)
L
0

Perhaps this Java 11 & Spring solution will be useful to someone:

private void removeOldBackupFolders(Path folder, String name) throws IOException {
    var current = System.currentTimeMillis();
    var difference = TimeUnit.DAYS.toMillis(7);

    BiPredicate<Path, BasicFileAttributes> predicate =
        (path, attributes) ->
            path.getFileName().toString().contains(name)
                && (current - attributes.lastModifiedTime().toMillis()) > difference;

    try (var stream = Files.find(folder, 1, predicate)) {
      stream.forEach(
          path -> {
            try {
              FileSystemUtils.deleteRecursively(path);

              log.warn("Deleted old backup {}", path.getFileName());
            } catch (IOException lambdaEx) {
              log.error("", lambdaEx);
            }
          });
    }
}

The BiPredicate is used to filter files (i.e. files & folder in Java) by name and age.

FileSystemUtils.deleteRecursively() is a Spring method that recursively removes files & folders. You can change that to something like NIO.2 Files.files.walkFileTree() if you don't want to use Spring dependencies.

I've set the maxDepth of Files.find() to 1 based on my use case. You can set to it unlimited Integer.MAX_VALUE and risk irreversibly deleting your dev FS if you are not careful.

Example logs based on var difference = TimeUnit.MINUTES.toMillis(3):

2022-05-20 00:54:15.505  WARN 24680 --- [       single-1] u.t.s.service.impl.BackupServiceImpl     : Deleted old backup backup_20052022_1652989557462
2022-05-20 00:54:15.506  WARN 24680 --- [       single-1] u.t.s.service.impl.BackupServiceImpl     : Deleted old backup backup_20052022_1652989558474
2022-05-20 00:54:15.507  WARN 24680 --- [       single-1] u.t.s.service.impl.BackupServiceImpl     : Deleted old backup backup_20052022_1652989589723
2022-05-20 00:54:15.508  WARN 24680 --- [       single-1] u.t.s.service.impl.BackupServiceImpl     : Deleted old backup backup_20052022_1652989674083

Notes:

  • The stream of Files.find() must be wrapped inside of a try-with-resource (utilizing AutoCloseable) or handled the old-school way inside of a try-finally to close the stream.

  • A good example of Files.walkFileTree() for copying (can be adapted for deletion): https://mcmap.net/q/370908/-java-8-copy-directory-recursively

Lara answered 19/5, 2022 at 20:16 Comment(0)
M
-1

Using Apache commons-io and joda:

        if ( FileUtils.isFileOlder(f, DateTime.now().minusDays(30).toDate()) ) {
            f.delete();
        }
Mohave answered 16/12, 2015 at 21:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.