Supprimer tous les fichiers du répertoire (mais pas du répertoire) - une solution de doublure


201

Je veux supprimer tous les fichiers du répertoire ABC.

Lorsque j'ai essayé, FileUtils.deleteDirectory(new File("C:/test/ABC/"));il supprime également le dossier ABC.

Existe-t-il une solution à une ligne où je peux supprimer des fichiers dans le répertoire mais pas dans le répertoire?


2
C'est parce que .deleteDirectory (même le nom l'indique) est utilisé pour supprimer les répertoires. Il obtiendra le répertoire dans lequel il se trouve si le fichier n'est pas un répertoire.
user1534664

Essayez de rechercher d'autres fonctions dans la classe FileUtils, qui suppriment les fichiers au lieu de ceux du répertoire.
user1534664


1
Pourquoi avez-vous spécifiquement besoin d'une doublure? Les performances ne peuvent pas être les critères, car toute méthode de bibliothèque tierce ne le fera que récursivement. Cela vous donnerait donc les mêmes performances?
Rohit Jain

1
Une chose que vous pouvez faire est de supprimer le répertoire, puis de le recréer. Nous avons constaté que l'utilisation rm -rf directory; mkdir directoryétait plus rapide que l'utilisation FileUtils.cleanDirectory.
Joshua Pinter

Réponses:


362
import org.apache.commons.io.FileUtils;

FileUtils.cleanDirectory(directory); 

Cette méthode est disponible dans le même fichier. Cela supprimera également de manière récursive tous les sous-dossiers et fichiers qui s'y trouvent.

Documents: org.apache.commons.io.FileUtils.cleanDirectory


49
Sympa, aussi pour empêcher les gens d'avoir à chercher cela; voici l'importation: import org.apache.commons.io.FileUtils;
Paul Gregoire

5
Je dois toujours chercher pourquoi l'importation est introuvable. C'est parce qu'il faut le télécharger sur apache.org .
Tomáš Zato - Rétablir Monica le

jolie solution. Vérifiez cette bibliothèque par gradle: compile "commons-io: commons-io: +"
Leo Nguyen

1
Dépendance Gradle - groupe de compilation: 'commons-io', nom: 'commons-io', version: '2.5'.
Jaydev

Notez que nous avons trouvé que l'appel rm -rf directoryétait beaucoup plus efficace que l'utilisation FileUtils.cleanDirectory.
Joshua Pinter

267

Voulez-vous dire comme?

for(File file: dir.listFiles()) 
    if (!file.isDirectory()) 
        file.delete();

Cela supprimera uniquement les fichiers, pas les répertoires.


65
C'est certainement la meilleure réponse, car elle n'utilise pas de bibliothèque externe!
AlexWien

10
@amar mais même alors: quand il y a une méthode standard, il n'y a absolument aucune raison d'utiliser une méthode externe qui fait la même chose. Un jour, il pourrait vouloir se débarrasser de la bibliothèque, ou la bibliothèque n'est plus prise en charge, ou n'est pas autorisée à utiliser la bibliothèque pour des raisons de licence, etc. (Tout cela peut ne pas être un problème pour cette bibliothèque spécifique, mais s'applique à beaucoup d'autres)
AlexWien

10
Cela ne supprimera pas tout si vous avez des sous-répertoires dans le répertoire racine "dir".
Tiago

2
@TiagoT Vrai, cela ne supprimera pas les sous-répertoires qui ne sont pas vides.
Peter Lawrey

4
for(File file: dir.listFiles())est probablement censé être .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.

62

La réponse de Peter Lawrey est excellente car elle est simple et ne dépend de rien de spécial, et c'est la façon dont vous devez le faire. Si vous avez besoin de quelque chose qui supprime également les sous-répertoires et leur contenu, utilisez la récursivité:

void purgeDirectory(File dir) {
    for (File file: dir.listFiles()) {
        if (file.isDirectory())
            purgeDirectory(file);
        file.delete();
    }
}

Pour épargner des sous-répertoires et leur contenu (partie de votre question), modifiez comme suit:

void purgeDirectoryButKeepSubDirectories(File dir) {
    for (File file: dir.listFiles()) {
        if (!file.isDirectory())
            file.delete();
    }
}

Ou, puisque vous vouliez une solution à une ligne:

for (File file: dir.listFiles())
    if (!file.isDirectory())
        file.delete();

L'utilisation d'une bibliothèque externe pour une tâche aussi banale n'est pas une bonne idée à moins que vous n'ayez besoin de cette bibliothèque pour autre chose de toute façon, auquel cas il est préférable d'utiliser du code existant. Vous semblez utiliser la bibliothèque Apache de toute façon, utilisez donc sa FileUtils.cleanDirectory()méthode.


1
D'un autre côté, si personne n'est le premier à utiliser la bibliothèque externe, alors il est moins probable que d'autres s'attendent à trouver un comportement similaire dans cette bibliothèque externe, et moins susceptibles qu'ils y regardent ... n'avons-nous pas assez Pas inventé ici-bas? Si la bibliothèque est cohérente et facile à ajouter à mon projet, je préfère presque toujours ajouter la bibliothèque.
JB Rainsberger

33

Flux Java 8

Cela supprime uniquement les fichiers de ABC (les sous-répertoires ne sont pas modifiés):

Arrays.stream(new File("C:/test/ABC/").listFiles()).forEach(File::delete);

Cela supprime uniquement les fichiers de l' ABC (et des sous-répertoires):

Files.walk(Paths.get("C:/test/ABC/"))
                .filter(Files::isRegularFile)
                .map(Path::toFile)
                .forEach(File::delete);

^ Cette version nécessite de gérer l'IOException


1
Le second ne supprime pas les sous-répertoires (testé)
edwise

1
@edwise Oui, il supprime tous les fichiers de ABC et tous les fichiers des sous-répertoires. L'anglais est un peu ambigu.
NonlinearFruit

11

Ou pour l'utiliser en Java 8:

try {
  Files.newDirectoryStream( directory ).forEach( file -> {
    try { Files.delete( file ); }
    catch ( IOException e ) { throw new UncheckedIOException(e); }
  } );
}
catch ( IOException e ) {
  e.printStackTrace();
}

Dommage que la gestion des exceptions soit si encombrante, sinon ce serait un monoplace ...


Comment savez-vous que ce fichier est réellement un fichier et non un répertoire?
Stephan

1
Il supprime également le répertoire, donc ce n'est pas une solution au problème du sujet
Marx

5
public class DeleteFile {
    public static void main(String[] args) {
        String path="D:\test"; 
        File file = new File(path);
        File[] files = file.listFiles(); 
        for (File f:files) 
        {if (f.isFile() && f.exists) 
            { f.delete();
system.out.println("successfully deleted");
            }else{
system.out.println("cant delete a file due to open or error");
} }  }}

2

Une autre solution Java 8 Stream pour supprimer tout le contenu d'un dossier, sous-répertoires inclus, mais pas le dossier lui-même.

Usage:

Path folder = Paths.get("/tmp/folder");
CleanFolder.clean(folder);

et le code:

public interface CleanFolder {
    static void clean(Path folder) throws IOException {

        Function<Path, Stream<Path>> walk = p -> {
            try { return Files.walk(p);
        } catch (IOException e) {
            return Stream.empty();
        }};

        Consumer<Path> delete = p -> {
            try {
                Files.delete(p);
            } catch (IOException e) {
            }
        };

        Files.list(folder)
            .flatMap(walk)
            .sorted(Comparator.reverseOrder())
            .forEach(delete);
    }
}

Le problème avec chaque solution de flux impliquant Files.walk ou Files.delete est que ces méthodes génèrent des IOException qui sont difficiles à gérer dans les flux.

J'ai essayé de créer une solution la plus concise possible.


Plutôt que de retourner un null dans la fonction walk, il serait préférable de renvoyer un flux vide (Stream.empty ()). C'est plus propre et la fonction renvoie toujours un flux. Null doit être évité autant que possible.
kaba713

Merci, j'ai amélioré la réponse avec votre suggestion
détourner le

2

Pour supprimer tous les fichiers du répertoire, dites "C: \ Exemple"

File file = new File("C:\\Example");      
String[] myFiles;    
if (file.isDirectory()) {
    myFiles = file.list();
    for (int i = 0; i < myFiles.length; i++) {
        File myFile = new File(file, myFiles[i]); 
        myFile.delete();
    }
}

2

rm -rfétait beaucoup plus performant que FileUtils.cleanDirectory.

Il ne s'agit pas d'une solution monoligne, mais après une analyse comparative approfondie, nous avons constaté que l'utilisation rm -rfétait plusieurs fois plus rapide que l'utilisation FileUtils.cleanDirectory.

Bien sûr, si vous avez un répertoire petit ou simple, cela n'aura pas d'importance, mais dans notre cas, nous avions plusieurs gigaoctets et des sous-répertoires profondément imbriqués où cela prendrait plus de 10 minutes avec FileUtils.cleanDirectoryet seulement 1 minute avec rm -rf.

Voici notre implémentation Java approximative pour ce faire:

// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean clearDirectory( File file ) throws IOException, InterruptedException {

    if ( file.exists() ) {

        String deleteCommand = "rm -rf " + file.getAbsolutePath();
        Runtime runtime = Runtime.getRuntime();

        Process process = runtime.exec( deleteCommand );
        process.waitFor();

        file.mkdirs(); // Since we only want to clear the directory and not delete it, we need to re-create the directory.

        return true;
    }

    return false;

}

Il vaut la peine d'essayer si vous avez affaire à des répertoires volumineux ou complexes.


1
package com;
import java.io.File;
public class Delete {
    public static void main(String[] args) {

        String files; 
        File file = new File("D:\\del\\yc\\gh");
        File[] listOfFiles = file.listFiles(); 
        for (int i = 0; i < listOfFiles.length; i++) 
        {
            if (listOfFiles[i].isFile()) 
            {
                files = listOfFiles[i].getName();
                System.out.println(files);
                if(!files.equalsIgnoreCase("Scan.pdf"))
                {
                    boolean issuccess=new File(listOfFiles[i].toString()).delete();
                    System.err.println("Deletion Success "+issuccess);
                }
            }
        }
    }
}

Si vous souhaitez supprimer tous les fichiers, supprimez

if(!files.equalsIgnoreCase("Scan.pdf"))

déclaration, cela fonctionnera.


0

Je pense que cela fonctionnera (basé sur la réponse précédente de NonlinearFruit):

Files.walk(Paths.get("C:/test/ABC/"))
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .filter(item -> !item.getPath().equals("C:/test/ABC/"))
                .forEach(File::delete);

À votre santé!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.