web-dev-qa-db-ja.com

Javaを使用して同じプレフィックス文字列を持つファイルを削除する

ファイル名に同じ接頭辞を持つ_dailyReport__というディレクトリ内に約500個のテキストファイルがあります。

ファイルの後半は、ファイルの日付です。 (たとえば、_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);
        }
_

しかし、特定のプレフィックス(たとえば、8か月目の_dailyReport08_)を持つファイルを削除できますか?_rm -rf dailyReport08*.txt_を使用すると、シェルスクリプトで簡単に削除できます。

しかし、File f=new File("dailyReport_08*.txt");はJava(予想どおり)では機能しません。

これで、Java ループを実行せずにでディレクトリを検索してファイルを検索できますか?

シェルスクリプトで使用される_*_に類似したいくつかの特殊文字を使用してこれを達成できますか?

30
Sangeet Menon

いいえ、できません。 Javaは低レベル言語です-シェルスクリプトと比較して-したがって、このようなことはより明示的に行われなければなりません。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() );
    }
}
39
BegemoT

ループを使用できます

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

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引数を変更します。ファイルとパスの間で変換することもできます。 Java> = 8。

8
tb-

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

私はパーティーに遅れていることを知っています。ただし、今後の参考のために、ループを含まない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
Lucas T

ワイルドカードはありませんが、 FilenameFilter を実装し、startsWith("dailyReport_")でパスを確認できます。次にFile.listFiles(filter)を呼び出すと、ループ処理してdelete()を呼び出すことができるファイルの配列が得られます。

3
Jon Lin

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)
2
Niraj Sonawane

BegemoTに同意します。

ただし、最適化は1つだけです。単純な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
bvdb

ループなしではできません。しかし、このループを強化できます。まず、質問をしてください:「ループ内での検索と削除の問題は何ですか?」何らかの理由で遅すぎる場合は、ループを別のスレッドで実行するだけで、ユーザーインターフェイスに影響を与えません。

その他のアドバイス-毎日のレポートを別のフォルダーに入れると、すべてのコンテンツでこのフォルダーを削除できるようになります。

1

Apache FileUtils をご覧ください。多くの便利なファイル操作が可能です。

0
Adriaan Koster
new Java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
0
Lolik Samuel