Delete Files with same Prefix String using Java
Asked Answered
G

11

41

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, dailyReport_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?

Glossal answered 30/8, 2011 at 8:26 Comment(5)
What wrong with looping?Souza
i also feels the same... why not loop?Cornelison
I know its possible with loop...but as I said I might be having a large number of files(500 is just a number)...so instead of using a loop if its possible the other way around like a shell script I feel that would be better...Glossal
@S.M.09: so you want to do something on a big number on inputs. Sounds like you need a loop. Again: why don't you want a loop? Do you think it's somehow slower? Hint: even the shell will need to loop at some point, you just don't see that loop.Succinctorium
If you like the shell, there is an answer to this question that may help.Lisandralisbeth
H
52

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() );
    }
}
Huh answered 30/8, 2011 at 8:33 Comment(3)
Thumb up! No for loop at all.Souza
@user802421: There is a for loop but, I intended to avoid a loop for searching files with pattern...and as I said this gives a faster result to a logic I tried with a loop searching for files and deleting when found one....Glossal
These days you could just replace the FilenameFilter object with a lambda: folder.listFiles((dir, name) -> name.matches("dailyReport_08.*\\.txt"));Pursy
P
41

You can use a loop

for (File f : directory.listFiles()) {
    if (f.getName().startsWith("dailyReport_")) {
        f.delete();
    }
}
Philippine answered 30/8, 2011 at 8:33 Comment(0)
V
12

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)
Viehmann answered 29/12, 2017 at 11:5 Comment(0)
D
10

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.

Deirdredeism answered 6/7, 2015 at 18:17 Comment(1)
This is all actually available as of Java 7.Leblanc
W
6

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.

Waterfall answered 13/6, 2016 at 7:33 Comment(2)
I don't think this solution avoids a loop, it just uses the newer syntax.Heloise
@jartaud, yes. Not in the usual sense but it is a iterating operation. It is also a terminal operation on the stream.Waterfall
L
5

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();
}
Loriannlorianna answered 30/8, 2011 at 8:37 Comment(1)
This code would delete anything(including non txt files) starting with dailyReport_08 probably would have also check the extension as well...but the code given BegemoT gives the perfect result..Thanks any wayGlossal
T
3

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.

Tribesman answered 30/8, 2011 at 8:33 Comment(0)
I
3

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 !

Isar answered 7/8, 2013 at 11:22 Comment(0)
M
1

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.

Musetta answered 30/8, 2011 at 8:36 Comment(1)
A monthly folder agreed!!!....could have gone for a monthly folder but then certain requirements like merging files(of different months) could then become tedious....And looping as already stated large no of files...Glossal
I
1

or in scala

new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
Imponderabilia answered 5/11, 2017 at 14:54 Comment(0)
Q
0

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

Quechua answered 30/8, 2011 at 10:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.