Java, liste uniquement les sous-répertoires d'un répertoire, pas les fichiers

100

En Java, comment répertorier uniquement les sous-répertoires d'un répertoire?

Je voudrais utiliser la fonctionnalité java.io.File, quelle est la meilleure méthode en Java pour cela?

Lokesh Paunikar
la source

Réponses:

141

Vous pouvez utiliser la classe File pour répertorier les répertoires.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

Mettre à jour

Le commentaire de l'auteur sur ce post voulait un moyen plus rapide, bonne discussion ici: Comment récupérer une liste de répertoires RAPIDEMENT en Java?

Fondamentalement:

  1. Si vous contrôlez la structure des fichiers, j'essaierais d'éviter de me retrouver dans cette situation.
  2. Dans Java NIO.2, vous pouvez utiliser la fonction de répertoires pour renvoyer un itérateur afin de permettre une plus grande mise à l'échelle. La classe de flux d'annuaire est un objet que vous pouvez utiliser pour parcourir les entrées d'un annuaire.
Mohamed Mansour
la source
salut, merci pour la réponse. Mais je n'ai pas à parcourir tous les éléments d'un répertoire. Je dois lister directement le sous-répertoire du répertoire. B'coz J'ai beaucoup de fichiers et seulement quelques sous-répertoires dans un répertoire donc, vérifier isDirectory () prend du temps. Veuillez me répondre d'une autre manière.
Lokesh Paunikar le
J'ai mis à jour mon message, en particulier, jetez un œil au commentaire de Jon Skeet sur la question. Et la réponse NIO depuis Java NIO 2 a un itérateur pour la fonction de répertoires qui renvoie un flux de répertoires.
Mohamed Mansour
De quel commentaire de Skeet parlez-vous? Quelle est la réponse la plus performante ici?
Stealth Rabbi
107

Une solution Java 8 très simple:

File[] directories = new File("/your/path/").listFiles(File::isDirectory);

Cela équivaut à utiliser un FileFilter (fonctionne également avec l'ancien Java):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});
headsvk
la source
4
Comment fonctionne le double deux-points ::dans ce cas?
snickers10m
J'ai remarqué qu'aucune autre réponse n'utilise FileFilter, j'ai donc ajouté la version équivalente sans utiliser de références de méthode. Pour plus d'informations sur les références de méthode, reportez-vous à cette question SO ou à cet article .
headsvk
cela obtient-il des sous-répertoires ou simplement les répertoires directement sous / votre / chemin /?
amadain
@amadain pas de récursivité comme prévu docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
headsvk
14

@Mohamed Mansour vous y étiez presque ... l'argument "dir" que vous utilisiez est en fait le chemin actuel, donc il retournera toujours vrai. Afin de voir si l'enfant est un sous-répertoire ou non, vous devez tester cet enfant.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));
Javier Buzzi
la source
7

Si vous êtes intéressé par une solution utilisant Java 7 et NIO.2, cela pourrait ressembler à ceci:

private static class DirectoriesFilter implements Filter<Path> {
    @Override
    public boolean accept(Path entry) throws IOException {
        return Files.isDirectory(entry);
    }
}

try (DirectoryStream<Path> ds = Files.newDirectoryStream(FileSystems.getDefault().getPath(root), new DirectoriesFilter())) {
        for (Path p : ds) {
            System.out.println(p.getFileName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
voo
la source
3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);
bcangas97
la source
Bonjour et bienvenue sur StackOverflow! Pouvez-vous élaborer un peu votre réponse? Vous aimez expliquer des parties intéressantes de vos extraits de code ou créer un lien vers la documentation pour une lecture ultérieure?
Richard-Degenne
Cela devrait être la bonne réponse car elle fournit un objet File avec le chemin canonique complet. Cela peut être vieux, mais cela vaut la peine de le souligner
Jero Dungog
2

Pour ceux qui s'intéressent également à Java 7 et NIO, il existe une solution alternative à la réponse de @ voo ci-dessus . Nous pouvons utiliser un try-with-resources qui appelle Files.find()et une fonction lambda qui est utilisée pour filtrer les répertoires.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;


final Path directory = Paths.get("/path/to/folder");

try (Stream<Path> paths = Files.find(directory, Integer.MAX_VALUE, (path, attributes) -> attributes.isDirectory())) {
    paths.forEach(System.out::println);
} catch (IOException e) {
    ...
}

Nous pouvons même filtrer les répertoires par nom en modifiant la fonction lambda:

(path, attributes) -> attributes.isDirectory() && path.toString().contains("test")

ou par date:

final long now = System.currentTimeMillis();
final long yesterday = new Date(now - 24 * 60 * 60 * 1000L).getTime();

// modified in the last 24 hours
(path, attributes) -> attributes.isDirectory() && attributes.lastModifiedTime().toMillis() > yesterday
HugoTeixeira
la source
2

Je souhaite utiliser la fonctionnalité java.io.File,

En 2012 (date de la question) oui, pas aujourd'hui. java.nioL'API doit être privilégiée pour de telles exigences.

Terrible avec tant de réponses, mais pas la manière simple que j'utiliserais Files.walk().filter().collect().

Globalement, deux approches sont possibles:

1) Files.walk(Path start, )n'a pas de maxDepthlimites alors que

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)permet de le paramétrer.

Sans spécifier de limitation de profondeur, cela donnerait:

Path directory = Paths.get("/foo/bar");

try {
    List<Path> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

Et si pour des raisons d'héritage, vous devez obtenir une liste, Filevous pouvez simplement ajouter une map(Path::toFile)opération avant la collecte:

Path directory = Paths.get("/foo/bar");

try {
    List<File> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .map(Path::toFile)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}
davidxxx
la source
Il y a aussi Files.list(Path)ce qui est probablement le même que Files.walk(Path,1).
David L. le
@David L Indeed Files.list(Path)est une alternative juste si nous ne voulons pas itérer récursivement les dossiers. Pour itérer les dossiers de manière récursive, walk()convient mieux.
davidxxx le
1

La solution qui a fonctionné pour moi est absente de la liste des réponses. Par conséquent, je poste cette solution ici:

File[]dirs = new File("/mypath/mydir/").listFiles((FileFilter)FileFilterUtils.directoryFileFilter());

Ici, j'ai utilisé org.apache.commons.io.filefilter.FileFilterUtilsApache commons-io-2.2.jar. Sa documentation est disponible ici: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html

Abhishek Oza
la source
0

Étant donné un répertoire de départ comme un String

  1. Créez une méthode qui prend un Stringchemin comme paramètre. Dans la méthode:
  2. Créer un nouvel objet File basé sur le répertoire de départ
  3. Obtenez un tableau de fichiers dans le répertoire actuel à l'aide de la listFilesméthode
  4. Boucle sur le tableau de fichiers
    1. S'il s'agit d'un fichier, continuez la boucle
    2. S'il s'agit d'un répertoire, imprimez le nom et recurse sur ce nouveau chemin de répertoire
Jonathon Faust
la source
salut, merci pour la réponse. Mais je n'ai pas à parcourir tous les éléments d'un répertoire. Je dois lister directement le sous-répertoire du répertoire. B'coz J'ai beaucoup de fichiers et seulement quelques sous-répertoires dans un répertoire donc, vérifier isDirectory () prend du temps. Veuillez me répondre d'une autre manière.
Lokesh Paunikar
0

Voici la solution pour mon code. Je viens de faire un petit changement par rapport à la première réponse . Cela listera tous les dossiers uniquement dans le répertoire souhaité ligne par ligne:

try {
            File file = new File("D:\\admir\\MyBookLibrary");
            String[] directories = file.list(new FilenameFilter() {
              @Override
              public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
              }
            });
            for(int i = 0;i < directories.length;i++) {
                if(directories[i] != null) {
                    System.out.println(Arrays.asList(directories[i]));

                }
            }
        }catch(Exception e) {
            System.err.println("Error!");
        }
Tabby Auguste
la source