Удалить файлы с той же строкой префикса, используя 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?
Ответы
Ответ 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())