开发者

Delete Files with same Prefix String using Java

开发者 https://www.devze.com 2023-03-31 12:11 出处:网络
I have around 500 text files inside a directory with each with the same prefix in their filename, for example: dailyReport_.

I have around 500 text files inside a directory with each with the same prefix in their filename, for example: dailyReport_.

The latter part of the file is the date of the file. (For example dailyReport_08262011.txt, d开发者_StackOverflow社区ailyReport_08232011.txt)

I want to delete these files using a Java procedure. (I could go for a shell script and add it a job in the crontab but the application is meant to used by laymen).

I can delete a single file using something like this:

try{
    File f=new File("dailyReport_08232011.txt");
    f.delete();
}
catch(Exception e){ 
    System.out.println(e);
}

but can I delete the files having a certain prefix? (e.g. dailyReport08 for the 8th month) I could easily do that in shell script by using rm -rf dailyReport08*.txt .

But File f=new File("dailyReport_08*.txt"); doesnt work in Java (as expected).

Now is anything similar possible in Java without running a loop that searches the directory for files?

Can I achieve this using some special characters similar to * used in shell script?


No, you can't. Java is rather low-level language -- comparing with shell-script -- so things like this must be done more explicetly. You should search for files with required mask with folder.listFiles(FilenameFilter), and iterate through returned array deleting each entry. Like this:

final File folder = ...
final File[] files = folder.listFiles( new FilenameFilter() {
    @Override
    public boolean accept( final File dir,
                           final String name ) {
        return name.matches( "dailyReport_08.*\\.txt" );
    }
} );
for ( final File file : files ) {
    if ( !file.delete() ) {
        System.err.println( "Can't remove " + file.getAbsolutePath() );
    }
}


You can use a loop

for (File f : directory.listFiles()) {
    if (f.getName().startsWith("dailyReport_")) {
        f.delete();
    }
}


Java 8 :

final File downloadDirectory = new File("directoryPath");   
    final File[] files = downloadDirectory.listFiles( (dir,name) -> name.matches("dailyReport_.*?" ));
    Arrays.asList(files).stream().forEach(File::delete)


With Java 8:

public static boolean deleteFilesForPathByPrefix(final String path, final String prefix) {
    boolean success = true;
    try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get(path), prefix + "*")) {
        for (final Path newDirectoryStreamItem : newDirectoryStream) {
            Files.delete(newDirectoryStreamItem);
        }
    } catch (final Exception e) {
        success = false;
        e.printStackTrace();
    }
    return success;
}

Simple version:

public static void deleteFilesForPathByPrefix(final Path path, final String prefix) {
    try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path, prefix + "*")) {
        for (final Path newDirectoryStreamItem : newDirectoryStream) {
            Files.delete(newDirectoryStreamItem);
        }
    } catch (final Exception e) { // empty
    }
}

Modify the Path/String argument as needed. You can even convert between File and Path. Path is preferred for Java >= 8.


I know I'm late to the party. However, for future reference, I wanted to contribute a java 8 stream solution that doesn't involve a loop.

It may not be pretty. I welcome suggestions to make it look better. However, it does the job:

Files.list(deleteDirectory).filter(p -> p.toString().contains("dailyReport_08")).forEach((p) -> {
    try {
        Files.deleteIfExists(p);
    } catch (Exception e) {
        e.printStackTrace();
    }
});

Alternatively, you can use Files.walk which will traverse the directory depth-first. That is, if the files are buried in different directories.


Use FileFilter like so:

File dir = new File(<path to dir>);
File[] toBeDeleted = dir.listFiles(new FileFilter() {
  boolean accept(File pathname) {
     return (pathname.getName().startsWith("dailyReport_08") && pathname.getName().endsWith(".txt"));
  } 

for (File f : toBeDeleted) {
   f.delete();
}


There isn't a wildcard but you can implement a FilenameFilter and check the path with a startsWith("dailyReport_"). Then calling File.listFiles(filter) gives you an array of Files that you can loop through and call delete() on.


I agree with BegemoT.

However, just one optimization: If you need a simple FilenameFilter, there is a class in the Google packages. So, in this case you do not even have to create your own anonymous class.

import com.google.common.io.PatternFilenameFilter;

final File folder = ...
final File[] files = folder.listFiles(new PatternFilenameFilter("dailyReport_08.*\\.txt"));

// loop through the files
for ( final File file : files ) {
    if ( !file.delete() ) {
        System.err.println( "Can't remove " + file.getAbsolutePath() );
    }
}

Enjoy !


You can't do it without a loop. But you can enhance this loop. First of all, ask you a question: "what's the problem with searching and removing in the loop?" If it's too slow for some reason, you can just run your loop in a separate thread, so that it will not affect your user interface.

Other advice - put your daily reports in a separate folder and then you will be able to remove this folder with all content.


or in scala

new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())


Have a look at Apache FileUtils which offers many handy file manipulations.

0

精彩评论

暂无评论...
验证码 换一张
取 消