2009-05-23 23 views
17

Quiero recopilar una lista de todos los archivos en un directorio, en particular, incluidos los subdirectorios. Me gusta no hacer las cosas yo mismo, así que estoy usando FileUtils.listFiles de Apache Commons IO. Así que tener algo como:Encontrar recursivamente solo directorios con FileUtils.listFiles

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); 
    } 
    } 
} 

El problema es que esto sólo parece encontrar archivos normales, no directorios:

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

ya estoy pasando TrueFileFilter a ambos de los filtros, por lo que puede' Pienso en algo más inclusivo. Quiero que aparezca en la lista: "foo", "foo/one_file", "foo/bar", "foo/bar/baz" (en cualquier orden).

También aceptaría soluciones que no sean FileUtils, pero me parece una tontería tener que escribir mi propio BFS, o incluso reunir el conjunto de directorios principales de la lista que obtengo. (Eso echaría de menos los subdirectorios vacíos de todos modos.) Esto está en Linux, FWIW.

Respuesta

0

Debería funcionar, en función de su API.

Aquí está mi propia versión de FileUtils, no tan completa como Commons IO, contiene solo lo que necesito. Busque findFiles o puede usar iterate para evitar la creación de listas enormes (en algún momento/la mayoría de las veces solo quiere hacer algo con esos archivos, por lo que recopilarlos en una lista no tiene sentido).

6

Si mira el source code y lee entre líneas en el JavaDoc, verá que, lamentablemente, esta API no está diseñada para hacer lo que desea. Devolverá una lista de archivos (no una lista de archivos y directorios) que coincidan con los argumentos proporcionados. En el código fuente - mire el método innerListFiles - verá que se buscan directorios y no agregado a la lista de resultados.

No conozco ninguna API pública que haga lo que usted desea. Con suerte, alguien más sabrá de uno. La mayoría probablemente será un DFS, no un BFS, que puede o no ser importante para sus propósitos. (Hasta ahora, todos código Java que he visto alguna vez que hizo un recorrido de árbol de directorios a través de una búsqueda en profundidad. Lo que no quiere decir que BFS no están ahí, por supuesto.)

Si realmente desea una lista de todo bajo un directorio determinado, es bastante fácil de hacer la suya propia. Pero entiendo tu deseo de no reinventar la rueda.

Nota: Es posible que Apache Commons Finder sea compatible con lo que necesita, pero esta biblioteca está en The Commons Sandbox, lo que significa que es más experimental en esta etapa. Puede o no estar completo y puede o no mantenerse. También puede ser pesado para lo que estás buscando.

+0

Gracias para el puntero: puedo terminar copiando eso y hacerlo funcionar. Supongo que esto es lo que obtengo al asumir que todo lo que es un archivo en Linux (directorios, enlaces, tuberías, dispositivos) es un archivo de la definición de Commons. –

+5

Hubiera supuesto lo mismo que usted, hasta que no funcionó. Realmente deberían hacer su JavaDoc más explícito para dejarlo en claro. – Eddie

+0

Guau, gracias por el puntero. No hay referencia en el javadoc de que los directorios estén excluidos. ¡No sé quién en la tierra asume que los directorios no son archivos! – WhyNotHugo

6

Evito las bibliotecas Java IO en la mayoría de mis aplicaciones no triviales, prefiriendo Commons VFS en su lugar. Creo que una llamada al this method con los parámetros adecuados logrará su objetivo, pero le otorgaré un largo camino por recorrer para la funcionalidad.

En concreto, este código va a hacer lo que quiere:

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

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

donde FileObject es una instancia de FileObject.

+0

"Este método" es un enlace roto. –

+0

Podemos arreglarlo :-) – Ben

1

Una solución completa Commons VFS más fácil +:

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

Ha intentado simplemente:

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

Parece que funciona para mí. Necesitará recursión, por supuesto.

Espero que ayude.

+0

Gracias, este funciona mejor para mí. No quiero agregar otra biblioteca para VFS. –

+0

El problema es que Java io es terriblemente lento. – Kieveli

19

Una respuesta de edad, pero esto funciona para mí:

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

muestra tanto:

que utilizo:

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

Sólo se muestran los directorios y archivos no ...

+0

Esto fue mucho más lento para mí que la respuesta del usuario573041 al punto que maté a mi aplicación. –

+0

Un sustituto de "new NotFileFilter (TrueFileFilter.INSTANCE)" es solo "FalseFileFilter.INSTANCE". Creo que su respuesta usando "FileUtils.listFilesAndDirs (...)" se ajusta mejor, una solución simple que el OP solicita. –

+0

Yo uso Collection c = FileUtils.listFilesAndDirs (nuevo archivo ("destino"), FalseFileFilter.INSTANCE, TrueFileFilter.INSTANCE); –

Cuestiones relacionadas