Exclua todos os arquivos do diretório (mas não o diretório) - uma solução de liner

201

Eu quero excluir todos os arquivos dentro do diretório ABC.

Quando tentei, FileUtils.deleteDirectory(new File("C:/test/ABC/"));ele também exclui a pasta ABC.

Existe uma solução de um liner onde eu possa excluir arquivos dentro do diretório, mas não no diretório?

Fahim Parkar
fonte
2
Isso porque .deleteDirectory (até o nome indica) é usado para excluir os diretórios. Ele obterá o diretório em que está se o arquivo não for um diretório.
precisa saber é o seguinte
Tente procurar outras funções dentro da classe FileUtils, que excluem arquivos em vez de diretórios.
precisa saber é o seguinte
1
Por que você precisa especificamente de uma linha? O desempenho não pode ser o critério, porque qualquer método de biblioteca de terceiros fará isso apenas recursivamente. Então, daria o mesmo desempenho?
Rohit Jain
1
Uma coisa que você pode fazer é excluir o diretório e depois recriá-lo. Descobrimos que o uso rm -rf directory; mkdir directoryera mais rápido que o uso FileUtils.cleanDirectory.
Joshua Pinter

Respostas:

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

FileUtils.cleanDirectory(directory); 

Existe esse método disponível no mesmo arquivo. Isso também exclui recursivamente todas as subpastas e arquivos abaixo delas.

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

Reddy
fonte
49
Bom, também para impedir que as pessoas tenham que procurar isso; aqui está a importação: import org.apache.commons.io.FileUtils;
Paul Gregoire
5
Ainda preciso procurar por que a importação não pode ser encontrada. É porque é preciso fazer o download do apache.org .
Tomáš Zato - Restabelece Monica
solução bonita. Verifique esta lib por gradle: compile "commons-io: commons-io: +"
Leo Nguyen
1
Dependência Gradle - grupo de compilação: 'commons-io', nome: 'commons-io', versão: '2.5'.
22416 Jaydev
Observe que descobrimos que ligar rm -rf directoryera muito mais eficiente do que usar FileUtils.cleanDirectory.
Joshua Pinter
267

Você quer dizer como?

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

Isso excluirá apenas arquivos, não diretórios.

Peter Lawrey
fonte
65
Esta é definitivamente a melhor resposta, já que ela não usa uma biblioteca externa!
AlexWien
10
@ amar, mas mesmo assim: quando existe um método padrão, não há absolutamente nenhuma razão para usar um método externo que faça a mesma coisa. Um dia, ele pode querer se livrar da lib, ou a lib não é mais suportada ou não tem permissão para usá-la por motivos de licença etc. (Isso tudo pode não ser um problema para essa lib específica, mas se aplica a muitos outros)
AlexWien
10
Isso falhará em excluir tudo se você tiver subdiretórios dentro do diretório "dir" raiz.
Tiago
2
@TiagoT True, isso não excluirá subdiretórios que não estão vazios.
Peter Lawrey
4
for(File file: dir.listFiles())é provavelmente quis dizer como .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.
62

A resposta de Peter Lawrey é ótima porque é simples e não depende de nada de especial, e é dessa maneira que você deve fazer. Se você precisar de algo que remova subdiretórios e seu conteúdo, use a recursão:

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

Para poupar subdiretórios e seu conteúdo (parte da sua pergunta), modifique da seguinte maneira:

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

Ou, já que você queria uma solução de uma linha:

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

Usar uma biblioteca externa para uma tarefa tão trivial não é uma boa idéia, a menos que você precise dessa biblioteca para outra coisa, nesse caso, é preferível usar o código existente. Você parece estar usando a biblioteca Apache de qualquer maneira, então use seu FileUtils.cleanDirectory()método.

ChrisB
fonte
1
Por outro lado, se ninguém é o primeiro a usar a biblioteca externa, é menos provável que outros esperem encontrar um comportamento semelhante nessa biblioteca externa e menos provável que eles procurem lá ... não temos o suficiente Não inventado aqui por aí? Se a biblioteca é coesa e fácil de adicionar ao meu projeto, quase sempre prefiro adicionar a biblioteca.
JB Rainsberger
33

Java 8 Stream

Isso exclui apenas arquivos do ABC (os subdiretórios são intocados):

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

Isso exclui apenas arquivos do ABC (e subdiretórios):

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

^ Esta versão requer manipulação do IOException

NonlinearFruit
fonte
1
O segundo não exclui os subdiretórios (testado)
edwise
1
@edwise Sim, ele exclui todos os arquivos do ABC e todos os arquivos dos subdiretórios. O inglês é um pouco ambíguo.
NonlinearFruit
11

Ou, para usar isso no Java 8:

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

É uma pena que o tratamento de exceções seja tão volumoso, caso contrário, seria uma linha única ...

Christian Ullenboom
fonte
Como você sabe que esse arquivo é realmente um arquivo e não um diretório?
Stephan
1
Ele diretório também de exclusão, por isso não é uma solução para o problema do tópico
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
fonte
2

Outra solução Java 8 Stream para excluir todo o conteúdo de uma pasta, incluindo os subdiretórios, mas não a própria pasta.

Uso:

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

e o código:

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

O problema com todas as soluções de fluxo que envolvem Files.walk ou Files.delete é que esses métodos lançam IOException, o que é difícil de tratar nos fluxos.

Tentei criar uma solução o mais concisa possível.

sequestro
fonte
Em vez de retornar um nulo na função walk, seria melhor retornar um fluxo vazio (Stream.empty ()). É mais limpo e a função sempre retorna um fluxo. Nulo deve ser evitado quando possível.
kaba713
Obrigado, eu melhorei a resposta com a sua sugestão
seqüestrar
2

Para excluir todos os arquivos do diretório, diga "C: \ Example"

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
fonte
2

rm -rfteve muito mais desempenho do queFileUtils.cleanDirectory .

Não é uma solução de uma linha, mas após extensos testes comparativos, descobrimos que o uso rm -rfera várias vezes mais rápido que o usoFileUtils.cleanDirectory .

Obviamente, se você tiver um diretório pequeno ou simples, isso não importará, mas, no nosso caso, tínhamos vários gigabytes e subdiretórios profundamente aninhados, onde levaria mais de 10 minutos com FileUtils.cleanDirectorye apenas 1 minuto comrm -rf .

Aqui está nossa implementação Java áspera para fazer isso:

// 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;

}

Vale a pena tentar se você estiver lidando com diretórios grandes ou complexos.

Joshua Pinter
fonte
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);
                }
            }
        }
    }
}

Se você deseja excluir todos os arquivos, remova

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

declaração funcionará.

Mahesh
fonte
0

Eu acho que isso funcionará (com base na resposta anterior do 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);

Felicidades!

dansouza
fonte