Удалить файлы с той же строкой префикса, используя Java - PullRequest
30 голосов
/ 30 августа 2011

У меня в каталоге около 500 текстовых файлов с одинаковым префиксом в имени файла скажем dailyReport_.

Последняя часть файла - это дата файла.(Например, dailyReport_08262011.txt, dailyReport_08232011.txt)

Я хочу удалить эти файлы с помощью процедуры Java (я мог бы пойти для сценария оболочки и добавить его в crontab, но приложение предназначено дляиспользуется неспециалистами).

Я могу удалить один файл, используя что-то вроде этого

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

, но могу ли я удалить файлы с определенным префиксом (например: dailyReport08 для 8-го месяца) Я мог бы легко сделать это в сценарии оболочки, используя rm -rf dailyReport08*.txt.

Но File f=new File("dailyReport_08*.txt"); не работает в Java (как и ожидалось).

Теперь в Java есть все, что возможно1020 * без выполнения цикла для поиска в каталоге файлов?

Можно ли добиться этого с помощью специальных символов, подобных *, используемых в сценарии оболочки?

Ответы [ 11 ]

39 голосов
/ 30 августа 2011

Нет, вы не можете.Java - это довольно низкоуровневый язык - по сравнению с shell-script - поэтому подобные вещи нужно делать более четко.Вам следует искать файлы с требуемой маской с помощью folder.listFiles (FilenameFilter) и перебирать возвращаемый массив, удаляя каждую запись.Как это:

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() );
    }
}
28 голосов
/ 30 августа 2011

Вы можете использовать цикл

for (File f : directory.listFiles()) {
    if (f.getName().startsWith("dailyReport_")) {
        f.delete();
    }
}
8 голосов
/ 06 июля 2015

С 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;
}

Простая версия:

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
    }
}

При необходимости измените аргумент Path / String.Вы даже можете конвертировать между File и Path.Путь предпочтителен для Java> = 8.

4 голосов
/ 30 августа 2011

Использовать FileFilter примерно так:

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();
}
3 голосов
/ 13 июня 2016

Я знаю, что опоздал на вечеринку. Тем не менее, для дальнейшего использования я хотел бы предложить потоковое решение Java 8, которое не включает цикл.

Это может быть не красиво. Я приветствую предложения, чтобы он выглядел лучше. Тем не менее, он делает свою работу:

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

В качестве альтернативы, вы можете использовать Files.walk , который будет сначала проходить через каталог. То есть, если файлы похоронены в разных каталогах.

3 голосов
/ 30 августа 2011

Подстановочный знак отсутствует, но вы можете реализовать FilenameFilter и проверить путь с помощью startsWith("dailyReport_").Затем вызов File.listFiles(filter) дает вам массив файлов, которые вы можете просмотреть и вызвать delete ().

2 голосов
/ 29 декабря 2017

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)
1 голос
/ 07 августа 2013

Я согласен с BegemoT.

Однако, только одна оптимизация: Если вам нужен простой FilenameFilter, в пакетах Google есть класс. Таким образом, в этом случае вам даже не нужно создавать свой собственный анонимный класс.

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() );
    }
}

Наслаждайтесь!

1 голос
/ 30 августа 2011

Вы не можете сделать это без цикла. Но вы можете улучшить этот цикл. Прежде всего, задайте вам вопрос: «в чем проблема с поиском и удалением в цикле?» Если по какой-то причине он слишком медленный, вы можете просто запустить цикл в отдельном потоке, чтобы он не влиял на ваш пользовательский интерфейс.

Другой совет - поместите ваши ежедневные отчеты в отдельную папку, и тогда вы сможете удалить эту папку со всем содержимым.

0 голосов
/ 05 ноября 2017
new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
...