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?

Fahim Parkar
la source
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

Reddy
la source
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.

Peter Lawrey
la source
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.

ChrisB
la source
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

NonlinearFruit
la source
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 ...

Christian Ullenboom
la source
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");
} }  }}
Manbumihu Manavan
la source
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.

détourner
la source
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();
    }
}
Mahesh Narwade
la source
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.

Joshua Pinter
la source
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.

Mahesh
la source
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é!

dansouza
la source