*
)があります。 たとえば次のコマンドは、現在のディレクトリにある、名前が.html
で終わるすべてのファイルを表示します。
% ls *.html
java.nio.file
パッケージにより、この便利な機能がプログラムで使用できるようになります。 各ファイル・システム実装でPathMatcher
が用意されています。 ファイル・システムのPathMatcher
を取得するには、FileSystem
クラスのgetPathMatcher(String)
メソッドを使用します。 次のコードでは、デフォルトのファイル・システムのPathMatcher
を取得しています。
String pattern = ...; PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
getPathMatcher
の文字列引数として、構文の種類と、一致させるパターンを渡します。 この例ではグロブ構文を指定しています。 グロブ構文について詳しくない場合は、グロブについてを参照してください。
グロブ構文は使用しやすく柔軟性に優れていますが、必要に応じて正規表現(regex)構文を使用することもできます。 正規表現に関する詳細は、『Regular Expressions』レッスンを参照してください。 ファイル・システム実装によっては、その他の構文がサポートされる場合があります。
他の形式の文字列ベース・パターン・マッチングを使用する場合は、独自のPathMatcher
クラスを作成できます。 このページで紹介するサンプルでは、グロブ構文を使用します。
PathMatcher
インスタンスを作成したら、それに対してファイルが一致するかを確認できます。 PathMatcher
インタフェースにはmatches
という1つのメソッドが含まれています。このメソッドはPath
を引数として受け入れ、パターンに一致するか一致しないかを表すboolean値を返します。 次のコードでは、名前が.java
または.class
で終わるファイルを検索し、これらのファイル名を標準出力に出力します。
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.{java,class}"); Path filename = ...; if (matcher.matches(filename)) { System.out.println(filename); }
特定のパターンに一致するファイルの検索は、ファイル・ツリーの探索と密接に関係します。 ファイルがファイル・システムのどこかにあると分かっているのに、その場所が分からないという経験はありませんか。 また、ファイル・ツリー内にある、特定のファイル拡張子を持つすべてのファイルを探し出す必要に迫られたことはないでしょうか。
サンプル・プログラムのFind
は、まさしくこの処理を示しています。 Find
はUNIXのfind
ユーティリティと類似していますが、機能が削減されています。 このサンプルを拡張して、他の機能を含めることができます。 たとえば、find
ユーティリティでは、-prune
オプションを使用して、検索対象からサブツリー全体を除外できます。 この機能は、preVisitDirectory
メソッドでSKIP_SUBTREE
を返すことで実装できます。 また、シンボリック・リンクをたどる-L
オプションの機能を実装するには、4つの引数を持つwalkFileTree
メソッドを使用し、この引数としてFOLLOW_LINKS
列挙定数を渡します(ただし、循環リンクがないことをvisitFile
メソッドで必ずテストしてください)。
このFindアプリケーションを実行するには、次の形式を使用します。
% java Find <path> -name "<glob_pattern>"
パターンは、ワイルド・カードがシェルによって解釈されないように、引用符で囲みます。 次に例を示します。
% java Find . -name "*.html"
以下は、Find
サンプル・プログラムのソース・コードです。
/** * 指定されたグロブ・パターンと一致するファイルを検索するサンプル・コード。 * グロブ・パターンの構成に関する詳細は、次の説明を参照してください。 * fileOps.html#glob * * パターンに一致するファイルまたはディレクトリは、標準出力に出力されます。 * また、一致した数も出力されます。 * * このアプリケーションを実行するときは、シェルがワイルド・カードを展開しないように、 * 次のようにグロブ・パターンを引用符で囲む必要があります。 * java Find . -name "*.java" */ import java.io.*; import java.nio.file.*; import java.nio.file.attribute.*; import static java.nio.file.FileVisitResult.*; import static java.nio.file.FileVisitOption.*; import java.util.*; public class Find { public static class Finder extends SimpleFileVisitor<Path> { private final PathMatcher matcher; private int numMatches = 0; Finder(String pattern) { matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern); } //グロブ・パターンとファイル名またはディレクトリ名を比較します。 void find(Path file) { Path name = file.getFileName(); if (name != null && matcher.matches(name)) { numMatches++; System.out.println(file); } } //一致した総数を標準出力に出力します。 void done() { System.out.println("Matched: " + numMatches); } //各ファイルに対してパターン・マッチング・メソッドを呼び出します。 @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { find(file); return CONTINUE; } //各ディレクトリに対してパターン・マッチング・メソッドを呼び出します。 @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { find(dir); return CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { System.err.println(exc); return CONTINUE; } } static void usage() { System.err.println("java Find <path> -name \"<glob_pattern>\""); System.exit(-1); } public static void main(String[] args) throws IOException { if (args.length < 3 || !args[1].equals("-name")) usage(); Path startingDir = Paths.get(args[0]); String pattern = args[2]; Finder finder = new Finder(pattern); Files.walkFileTree(startingDir, finder); finder.done(); } }
ファイル・ツリーの再帰的な探索については、ファイル・ツリーの探索で説明しています。