別に目新しくもなんともないのですが、なんとなく投稿してみます。
掲題のような処理を行うには、Java7で追加されてたFiles#walkFileTree()がよさそうです。
WalkFileTreeSample.java
import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.io.*; public class WalkFileTreeSample { public static void main(String[] args) throws IOException { Path start = Paths.get("/Users/daiki/go"); Files.walkFileTree(start, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { System.out.println(file); return FileVisitResult.CONTINUE; } }); } }
SimpleFileVisitorは普通のクラスであり、関数型インタフェースじゃないのでラムダ式は使えません。
上記ではファイルごとに呼び出されるメソッドのみをオーバーライドしてますが、他にもディレクトリを訪問する前に呼び出されるメソッド、後に呼び出されるメソッドなどがあり、オーバーライドすることで処理を挟むことができます。
別の例として、Java8で追加されてたFiles#walk()を使うこともできます。こちらはStream APIを使います。上のと結果を合わせるため、ディレクトリは除外しています。ちょっと気持ち悪い?
WalkSample.java
import java.io.IOException; import java.nio.file.*; import java.util.stream.Stream; public class WalkSample { public static void main(String[] args) throws IOException { Path start = Paths.get("/path/to/target"); try(Stream<Path> paths = Files.walk(start)) { paths.filter(path -> !Files.isDirectory(path)) .forEach(System.out::println); } } }
Java6以前であれば、再帰を使って自分で書くことになりますかね。ただファイル名を出力するだけなら、特に難しいことはありませんが。
WalkWithoutLibrarySample.java
import java.io.File; public class WalkWithoutLibrarySample { public static void main(String[] args) { File start = new File("/path/to/target"); walk(start); } private static void walk(File dir) { for(File file : dir.listFiles()) { if(file.isFile()) { System.out.println(file); } else { walk(file); } } } }