Подтвердить что ты не робот

Удалить файлы с той же строкой префикса, используя Java

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

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

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

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

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

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

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

В Java такая возможность невозможна без запуска цикла, который ищет каталог для файлов?

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

4b9b3361

Ответ 1

Нет, вы не можете. 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() );
    }
}

Ответ 2

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

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

Ответ 3

С 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

Используйте 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();
}

Ответ 5

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

Ответ 6

Я знаю, что опоздал на вечеринку. Тем не менее, для дальнейшего использования я хотел бы предложить потоковое решение 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, который будет сначала проходить по каталогу. Это если файлы похоронены в разных каталогах.

Ответ 7

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)

Ответ 8

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

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

Ответ 9

Я согласен с 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() );
    }
}

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

Ответ 10

Посмотрите Apache FileUtils, который предлагает много удобных манипуляций с файлами.

Ответ 11

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