Hapus semua file dalam direktori (tetapi bukan direktori) - satu solusi liner


201

Saya ingin menghapus semua file di dalam direktori ABC.

Ketika saya mencoba dengan FileUtils.deleteDirectory(new File("C:/test/ABC/"));itu juga menghapus folder ABC.

Apakah ada solusi satu liner di mana saya dapat menghapus file di dalam direktori tetapi tidak pada direktori?


2
Itu karena .deleteDirectory (bahkan namanya) - digunakan untuk menghapus direktori. Ini akan mendapatkan direktori itu jika file tersebut bukan direktori.
user1534664

Coba cari fungsi lain di dalam kelas FileUtils, yang menghapus file, bukan direktori.
user1534664


1
Mengapa Anda secara khusus membutuhkan one-liner? Kinerja tidak dapat menjadi kriteria, karena metode perpustakaan pihak ketiga mana pun, hanya akan melakukan itu secara rekursif. Jadi itu akan memberi Anda kinerja yang sama?
Rohit Jain

1
Satu hal yang dapat Anda lakukan adalah menghapus direktori dan kemudian membuatnya kembali. Kami menemukan bahwa menggunakan rm -rf directory; mkdir directorylebih cepat daripada menggunakan FileUtils.cleanDirectory.
Joshua Pinter

Jawaban:


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

FileUtils.cleanDirectory(directory); 

Ada metode ini tersedia di file yang sama. Ini juga akan menghapus semua sub-folder dan file di bawahnya secara rekursif.

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


49
Bagus, juga untuk mencegah orang harus melihat ini; inilah impornya: import org.apache.commons.io.FileUtils;
Paul Gregoire

5
Saya masih harus mencari mengapa impor tidak dapat ditemukan. Itu karena seseorang harus mengunduhnya dari apache.org .
Tomáš Zato - Reinstate Monica

solusi yang bagus. Periksa lib ini secara bertahap: kompilasi "commons-io: commons-io: +"
Leo Nguyen

1
Ketergantungan Gradle - kompilasi grup: 'commons-io', nama: 'commons-io', versi: '2.5'.
Jaydev

Catatan, kami menemukan panggilan rm -rf directoryjauh lebih efisien daripada menggunakan FileUtils.cleanDirectory.
Joshua Pinter

267

Maksud Anda suka?

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

Ini hanya akan menghapus file, bukan direktori.


65
Ini pasti jawaban yang lebih baik, karena tidak menggunakan lib eksternal!
AlexWien

10
@amar tetapi bahkan kemudian: ketika ada metode standar ada absolutley tidak ada alasan untuk menggunakan yang eksternal yang melakukan hal yang sama. Suatu hari ia mungkin ingin menyingkirkan lib, atau lib tidak lagi didukung, atau tidak diperbolehkan menggunakan lib karena alasan lisensi, dll. (Ini semua mungkin bukan masalah untuk lib spesifik ini, tetapi berlaku untuk banyak yang lain)
AlexWien

10
Ini akan gagal menghapus semuanya jika Anda memiliki subdirektori di dalam direktori "dir" root.
Tiago

2
@TiagoT Benar, ini tidak akan menghapus sub-direktori yang tidak kosong.
Peter Lawrey

4
for(File file: dir.listFiles())mungkin dimaksudkan sebagai .... for (File file : new java.io.File("C:\\DeleteMeFolder").listFiles())...
Hartmut P.

62

Jawaban Peter Lawrey luar biasa karena sederhana dan tidak tergantung pada sesuatu yang istimewa, dan itulah cara Anda harus melakukannya. Jika Anda memerlukan sesuatu yang juga menghapus subdirektori dan isinya, gunakan rekursi:

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

Untuk menyimpan subdirektori dan kontennya (bagian dari pertanyaan Anda), ubah sebagai berikut:

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

Atau, karena Anda menginginkan solusi satu baris:

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

Menggunakan perpustakaan eksternal untuk tugas sepele seperti itu bukanlah ide yang baik kecuali Anda membutuhkan perpustakaan ini untuk hal lain, dalam hal ini lebih disukai untuk menggunakan kode yang ada. Anda tampaknya menggunakan perpustakaan Apache, jadi gunakan FileUtils.cleanDirectory()metode ini.


1
Di sisi lain, jika tidak ada orang pertama yang menggunakan perpustakaan eksternal, maka kecil kemungkinan orang lain akan berharap untuk menemukan perilaku serupa di perpustakaan eksternal itu, dan kecil kemungkinannya mereka akan melihat di sana ... tidakkah kita punya cukup Tidak Diciptakan Di Sini? Jika perpustakaan itu kohesif dan mudah ditambahkan ke proyek saya, maka saya hampir selalu lebih suka menambahkan perpustakaan.
JB Rainsberger

33

Java 8 Stream

Ini hanya menghapus file dari ABC (sub-direktori tidak tersentuh):

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

Ini hanya menghapus file dari ABC (dan sub-direktori):

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

^ Versi ini membutuhkan penanganan IOException


1
Yang kedua tidak menghapus sub-direktori (diuji)
edwise

1
@ sebaliknya Ya, ini menghapus semua file dari ABC dan semua file dari sub-direktori. Bahasa Inggris sedikit ambigu.
NonlinearFruit

11

Atau untuk menggunakan ini di Java 8:

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

Sayang penanganan pengecualiannya sangat besar, jika tidak akan menjadi satu-liner ...


Bagaimana Anda tahu file yang IS file sebenarnya dan bukan sebuah direktori?
Stephan

1
Itu juga menghapus direktori, jadi itu bukan solusi untuk masalah dari topik
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

Solusi Java 8 Stream lainnya untuk menghapus semua konten folder, termasuk sub direktori, tetapi bukan folder itu sendiri.

Pemakaian:

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

dan kodenya:

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

Masalah dengan setiap solusi aliran yang melibatkan Files.walk atau Files.delete adalah bahwa metode ini melempar IOException yang merupakan rasa sakit untuk menangani dalam aliran.

Saya mencoba membuat solusi yang lebih ringkas mungkin.


Daripada mengembalikan fungsi null dalam berjalan, akan lebih baik untuk mengembalikan aliran kosong (Stream.empty ()). Lebih bersih dan fungsinya selalu mengembalikan aliran. Null harus dihindari bila memungkinkan.
kaba713

Terima kasih, saya meningkatkan jawaban dengan saran Anda
membajak

2

Untuk menghapus semua file dari direktori, katakan "C: \ Contoh"

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 -rfadalah jauh lebih performant dari FileUtils.cleanDirectory.

Bukan solusi satu-liner tetapi setelah benchmark yang luas, kami menemukan bahwa menggunakan rm -rfbeberapa kali lebih cepat daripada menggunakan FileUtils.cleanDirectory.

Tentu saja, jika Anda memiliki direktori kecil atau sederhana, itu tidak masalah, tetapi dalam kasus kami, kami memiliki beberapa gigabyte dan sub direktori yang bersarang di mana itu akan memakan waktu lebih dari 10 menit FileUtils.cleanDirectorydan hanya 1 menit rm -rf.

Inilah implementasi Java kami yang kasar untuk melakukan itu:

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

}

Pantas untuk dicoba jika Anda berurusan dengan direktori besar atau kompleks.


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

Jika Anda ingin menghapus semua file hapus

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

Pernyataan itu akan berhasil.


0

Saya pikir ini akan berhasil (berdasarkan jawaban NonlinearFruit sebelumnya):

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

Bersulang!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.