Подтвердить что ты не робот

Рекурсивно поиск только каталогов с FileUtils.listFiles

Я хочу собрать список всех файлов в каталоге, в частности, включая подкаталоги. Мне нравится не делать ничего, поэтому я использую 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" (в любом порядке).

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

4b9b3361

Ответ 1

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

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

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

Я использую:

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

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

Ответ 2

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

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

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

Примечание. Возможно, что Apache Commons Finder будет поддерживать то, что вам нужно, но эта библиотека находится в The Commons Sandbox, что означает, что это больше экспериментальной на этом этапе. Он может быть или не быть полным, и он может поддерживаться или не поддерживаться. Это также может быть тяжеловесом для того, что вы ищете.

Ответ 3

Я избегаю библиотек 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.

Ответ 4

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

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

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

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

Ответ 5

Более легкое + полное решение Commons VFS:

FileSystemManager fsManager = VFS.getManager();
FileObject fileObject = fsManager.resolveFile( "yourFileNameHere" );
FileObject[] files = fileObject.findFiles( new FileTypeSelector( FileType.FOLDER ) )

Ответ 6

Он должен работать на основе их API.

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