Рекурсивный поиск только каталогов с FileUtils.listFiles - PullRequest
18 голосов
/ 23 мая 2009

Я хочу собрать список всех файлов в каталоге, в частности, включая подкаталоги. Я сам не люблю что-то делать, поэтому использую FileUtils.listFiles от Apache Commons IO. Итак, у меня есть что-то вроде:

import java.io.File;
import java.util.Collection;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;

public class TestListFiles {
  public static void main(String[] args) {
    Collection<File> found = FileUtils.listFiles(new File("foo"),
        TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
    for (File f : found) {
      System.out.println("Found file: " + f);
    }
  }
}

Проблема в том, что это только для поиска обычных файлов, а не каталогов:

$ mkdir -p foo/bar/baz; touch foo/one_file
$ java -classpath commons-io-1.4.jar:. TestListFiles
Found file: foo/one_file

Я уже передаю TrueFileFilter обоим фильтрам, поэтому я не могу придумать ничего более инклюзивного. Я хочу это перечислить: "foo", "foo/one_file", "foo/bar", "foo/bar/baz" (в любом порядке).

Я бы также принял решения, отличные от FileUtils, но кажется глупым писать свою собственную BFS или даже собирать набор родительских каталогов из списка, который я получаю. (Это в любом случае пропустит пустые подкаталоги.) Это в Linux, FWIW.

Ответы [ 6 ]

19 голосов
/ 17 октября 2012

Старый ответ, но у меня это работает:

FileUtils.listFilesAndDirs(new File(dir), TrueFileFilter.INSTANCE, DirectoryFileFilter.DIRECTORY);

показывает оба:

Я использую:

FileUtils.listFilesAndDirs(new File(dir), new NotFileFilter(TrueFileFilter.INSTANCE), DirectoryFileFilter.DIRECTORY)

Показывает только каталоги, а не файлы ...

6 голосов
/ 01 февраля 2011

Вы пробовали просто:

File rootFolder = new File(...);
File[] folders = rootFolder.listFiles((FileFilter) FileFilterUtils.directoryFileFilter());

Кажется, это работает для меня. Конечно, вам понадобится рекурсия.

Надеюсь, это поможет.

6 голосов
/ 23 мая 2009

Я избегаю библиотек Java IO в большинстве моих нетривиальных приложений, предпочитая Commons VFS. Я полагаю, что вызов этого метода с соответствующими параметрами достигнет вашей цели, но я дам долгий путь для функциональности.

В частности, этот код будет делать то, что вы хотите:

    FileObject[] files = fileObject.findFiles(new FileSelector() {
        public boolean includeFile(FileSelectInfo fileInfo)  {
            return fileInfo.getFile().getType() == FileType.FOLDER; }

        public boolean traverseDescendents(FileSelectInfo fileInfo) {
            return true;
        }
    });

где fileObject является экземпляром FileObject.

6 голосов
/ 23 мая 2009

Если вы посмотрите на исходный код и прочитаете между строк в JavaDoc, вы увидите, что - к сожалению - этот API не предназначен для того, что вы хотите. Он вернет список файлов (не список файлов и каталогов ), которые соответствуют предоставленным аргументам. В исходном коде - посмотрите на метод innerListFiles - вы увидите, что каталоги ищутся и не добавляются в список результатов.

Я не знаю ни одного публичного API, который будет делать то, что вы хотите. Надеюсь, кто-то еще узнает об этом. Большинство из них, вероятно, будет DFS, а не BFS, что может иметь или не иметь значения для ваших целей. (Пока что весь Java-код, на который я когда-либо смотрел, проходил через дерево каталогов с помощью поиска в глубину. Что, конечно, не означает, что BFS там нет. )

Если вам действительно нужен список всего в данном каталоге, достаточно легко свернуть свой собственный. Но я понимаю ваше желание не изобретать велосипед.

Примечание: вполне возможно, что Apache Commons Finder будет поддерживать то, что вам нужно, но эта библиотека находится в «песочнице» Commons, что означает, что она более экспериментальна на данном этапе. Это может или не может быть полным, и это может или не может быть поддержано. Он также может быть тяжелым для того, что вы ищете.

1 голос
/ 06 февраля 2010

Более простой + полный Commons VFS решение:

FileSystemManager fsManager = VFS.getManager();
FileObject fileObject = fsManager.resolveFile( "yourFileNameHere" );
FileObject[] files = fileObject.findFiles( new FileTypeSelector( FileType.FOLDER ) )
0 голосов
/ 23 мая 2009

Должно работать, основываясь на их API.

Вот моя собственная версия FileUtils , не такая полная, как Commons IO, она содержит только то, что мне нужно. Ищите findFiles , или вы можете использовать iterate , чтобы избежать создания огромных списков (иногда / в большинстве случаев вы просто хотите что-то сделать с этими файлами, поэтому собирать их в Список не удается т имеет смысл).

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