전체 폴더와 내용을 삭제하는 방법?


187

응용 프로그램 사용자가 DCIM 폴더 (SD 카드에 있고 하위 폴더가 있음)를 삭제할 수 있기를 원합니다.

그렇다면 어떻게 가능합니까?


1
재귀적인 상향식 삭제 방법 이외의 다른 방법은?
Sarwar Erfan

매우 크거나 복잡한 디렉토리가있는 경우 rm -rf directory대신 대신 사용해야 합니다 FileUtils.deleteDirectory. 벤치마킹 후 여러 배 더 빠르다는 것을 알았습니다. 여기에서 샘플 구현을 확인하십시오. stackoverflow.com/a/58421350/293280
Joshua Pinter

답변:


301

DCIM 폴더는 시스템 폴더이므로 삭제할 수 없다는 것을 먼저 말씀 드리겠습니다. 전화에서 수동으로 삭제하면 해당 폴더의 내용은 삭제되지만 DCIM 폴더는 삭제되지 않습니다. 아래 방법을 사용하여 내용을 삭제할 수 있습니다.

의견에 따라 업데이트

File dir = new File(Environment.getExternalStorageDirectory()+"Dir_name_here"); 
if (dir.isDirectory()) 
{
    String[] children = dir.list();
    for (int i = 0; i < children.length; i++)
    {
       new File(dir, children[i]).delete();
    }
}

3
dir이 무엇인지 어떻게 선언합니까?
초보자

im 기본적으로 모든 사진을 삭제하려고하므로 중요하지 않습니다 DCIM은 사진이있는 한 삭제되지 않습니다 ... 그래서 100MEDIA를 삭제 해도이 폴더는 작업을 수행합니다
Beginner

1
dicm 폴더의 경로를 사용하여 디렉토리를 선언해야합니다. use file r = file (path);
chikka.anddev

3
사용 된 파일 디렉토리 = 새 파일 (Environment.getExternalStorageDirectory () + "/ DCIM / 100MEDIA");
초보자

1
@chiragshah 폴더를 삭제하고 폴더를 다시 생성하면 언급 된 폴더 이름으로 알 수없는 파일이 생성됩니다. 그 파일에 액세스하려고하면 Resource 또는 device busy 같은 예외가 발생합니다 . 내가 MD5 서명을
sha

529

다음과 같이 파일과 폴더를 재귀 적으로 삭제할 수 있습니다.

void deleteRecursive(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory())
        for (File child : fileOrDirectory.listFiles())
            deleteRecursive(child);

    fileOrDirectory.delete();
}

21
나는 효율성에 대한 테스트를 수행하지 않았지만 내 것이 더 강력하다고 생각합니다. chirag는 DCIM 폴더의 특정 경우에 대해 작동합니다. DCIM 내의 폴더에는 파일 만 포함되어야합니다 (즉, DCIM 내의 폴더에는 일반적으로 하위 폴더가 포함되지 않음). 내 버전은 깊이에 중첩 된 폴더를 삭제합니다. DCIM에 더 깊이 중첩 된 폴더 (예 DCIM\foo\bar\pic.jpg:)가 포함되도록 사용자가 자신의 SD 카드의 내용을 수정했을 가능성이 있습니다 .이 경우 chirag의 코드가 실패합니다.
teedyay

2
동료가 나에게 물었던 질문 : 폴더 자체에 심볼릭 링크가 있고이 코드를 실행하면 어떻게됩니까?
p4u144

1
@ p4u144 동료에게 천재가되어 주도록 하이 파이브를주세요! 잘 발견되었습니다! 솔직히 말해서이 코드가 기호 링크를 존중하고 따를 지 여부는 알지 못하지만 무한 루프가있을 것입니다. 당신은 그것을 테스트 공상합니까?
teedyay

8
@ p4u144 심볼릭 링크에 대해 걱정할 필요가 없습니다. "기호 링크를 사용하면 링크의 대상이 아닌 링크가 삭제됩니다." 에서 docs.oracle.com/javase/tutorial/essential/io/delete.html
코빈

3
가능한 NPE 가 있습니다. 파일을 읽을 때 I / O 오류가있는 경우 fileOrDirectory.listFiles()반환 될 수 null있습니다. 이것은 문서에 명확하게 나와 있습니다 : developer.android.com/reference/java/io/File.html#listFiles ()
Brian Yencho

67

명령 줄 인수를 사용하여 전체 폴더와 내용을 삭제할 수 있습니다.

public static void deleteFiles(String path) {

    File file = new File(path);

    if (file.exists()) {
        String deleteCmd = "rm -r " + path;
        Runtime runtime = Runtime.getRuntime();
        try {
            runtime.exec(deleteCmd);
        } catch (IOException e) { }
    }
}

위 코드의 사용법 예 :

deleteFiles("/sdcard/uploads/");

2
이게 동기식인지 비동기식인지 아십니까? 문서는 말을하지 않습니다 developer.android.com/reference/java/lang/...
누군가 어딘가에

2
나쁜 생각. 왜 껍질에 있습니까?
noamtm 2016 년


34

Kotlin에서는 패키지 deleteRecursively()에서 확장을 사용할 수 있습니다kotlin.io

val someDir = File("/path/to/dir")
someDir.deleteRecursively()

2
Java에서는 FilesKt.deleteRecursively(new File("/path/to/dir"));kotlin-stdlib를 사용 하는 경우 사용할 수 있습니다
Joonsoo

이 명령은 "/ dir"디렉토리 안에 내용이 있거나 "/ dir"디렉토리 안에 내용이있는 "/ dir"디렉토리를 삭제하며 디렉토리는?
Bhimbim

1
@Bhimbim lemme google docs "모든 자녀와 함께이 파일을 삭제하십시오.". 따라서 디렉토리는 내용뿐만 아니라 삭제됩니다
Dima Rostopira

@DimaRostopira 감사합니다!.
Bimbim

구조에 kotlin!
Tobi Oyelekan

15

아래 방법을 사용하여 파일과 하위 디렉토리가 포함 된 전체 기본 디렉토리를 삭제하십시오. 이 메소드를 다시 한 번 호출 한 후 기본 디렉토리의 delete () 디렉토리를 호출하십시오.

// For to Delete the directory inside list of files and inner Directory
public static boolean deleteDir(File dir) {
    if (dir.isDirectory()) {
        String[] children = dir.list();
        for (int i=0; i<children.length; i++) {
            boolean success = deleteDir(new File(dir, children[i]));
            if (!success) {
                return false;
            }
        }
    }

    // The directory is now empty so delete it
    return dir.delete();
}

모든 답변 중, 이것은 실제 답변이며 파일을 삭제 한 후에도 디렉토리를 삭제합니다.
zeeshan

파일 파일 = 새 파일 (Environment.getExternalStorageDirectory () + separator + "folder_name"+ separator); deleteDir (file); 그렇습니다. 감사합니다 :)
ashishdhiman2007

14

접근 방식은 파일 만 포함 된 폴더에 적합하지만 하위 폴더도 포함 된 시나리오를 찾는 경우 재귀가 필요합니다.

또한 반환 값을 캡처하여 파일을 삭제할 수 있는지 확인해야합니다.

포함

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

당신의 매니페스트에

void DeleteRecursive(File dir)
{
    Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
    if (dir.isDirectory())
    {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++)
        {
            File temp = new File(dir, children[i]);
            if (temp.isDirectory())
            {
                Log.d("DeleteRecursive", "Recursive Call" + temp.getPath());
                DeleteRecursive(temp);
            }
            else
            {
                Log.d("DeleteRecursive", "Delete File" + temp.getPath());
                boolean b = temp.delete();
                if (b == false)
                {
                    Log.d("DeleteRecursive", "DELETE FAIL");
                }
            }
        }

    }
    dir.delete();
}

5
(File currentFile : file.listFiles ()) {
Thorben

8

많은 답변이 있지만 조금 다르기 때문에 직접 추가하기로 결정했습니다. OOP를 기반으로합니다.)

디렉토리를 정리해야 할 때마다 도움이되는 DirectoryCleaner 클래스를 만들었습니다 .

public class DirectoryCleaner {
    private final File mFile;

    public DirectoryCleaner(File file) {
        mFile = file;
    }

    public void clean() {
        if (null == mFile || !mFile.exists() || !mFile.isDirectory()) return;
        for (File file : mFile.listFiles()) {
            delete(file);
        }
    }

    private void delete(File file) {
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                delete(child);
            }
        }
        file.delete();

    }
}

다음 방법으로이 문제를 해결하는 데 사용할 수 있습니다.

File dir = new File(Environment.getExternalStorageDirectory(), "your_directory_name");
new DirectoryCleaner(dir).clean();
dir.delete();

7

재귀 적으로 물건을 삭제할 필요가 없다면 다음과 같이 시도하십시오.

File file = new File(context.getExternalFilesDir(null), "");
    if (file != null && file.isDirectory()) {
        File[] files = file.listFiles();
        if(files != null) {
            for(File f : files) {   
                f.delete();
            }
        }
    }

6

Java에 서브 디렉토리 나 파일이 있으면 디렉토리를 삭제할 수 없습니다. 이 두 줄 간단한 솔루션을 사용해보십시오. 디렉토리 안의 디렉토리와 컨테스트가 삭제됩니다.

File dirName = new File("directory path");
FileUtils.deleteDirectory(dirName);

gradle 파일 에이 줄을 추가하고 프로젝트를 동기화하십시오.

compile 'org.apache.commons:commons-io:1.3.2'  

2 라이너로 간단합니다. 그러나 방법 중 하나만 사용하기 위해 전체 라이브러리를 설치하는 것은 비효율적입니다. 대신 이것을 사용하십시오
Kathir

gradle insert tip이 생명을 구했습니다.
Dracarys

5
public static void deleteDirectory( File dir )
{

    if ( dir.isDirectory() )
    {
        String [] children = dir.list();
        for ( int i = 0 ; i < children.length ; i ++ )
        {
         File child =    new File( dir , children[i] );
         if(child.isDirectory()){
             deleteDirectory( child );
             child.delete();
         }else{
             child.delete();

         }
        }
        dir.delete();
    }
}

5

android.os.FileUtils 참조, API 21에 숨겨져 있음

public static boolean deleteContents(File dir) {
    File[] files = dir.listFiles();
    boolean success = true;
    if (files != null) {
        for (File file : files) {
            if (file.isDirectory()) {
                success &= deleteContents(file);
            }
            if (!file.delete()) {
                Log.w("Failed to delete " + file);
                success = false;
            }
        }
    }
    return success;
}

출처 : https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/FileUtils.java#414


4

설명서 에 따르면 :

이 추상 패스 명이 디렉토리를 나타내지 않는 경우,이 메소드는 null를 돌려줍니다.

그래서 만약 당신이 확인해야 listFiles하다 null와 그렇지 않은 경우에만 계속

boolean deleteDirectory(File path) {
    if(path.exists()) {
        File[] files = path.listFiles();
        if (files == null) {
            return false;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                deleteDirectory(file);
            } else {
                boolean wasSuccessful = file.delete();
                if (wasSuccessful) {
                    Log.i("Deleted ", "successfully");
                }
            }
        }
    }
    return(path.delete());
}

1
이것이 정답입니다. 매력처럼 작동합니다!
MSeiz5

3

이것이 내가하는 일입니다 ... (간결하고 테스트 됨)

    ...
    deleteDir(new File(dir_to_be_deleted));
    ...

    // delete directory and contents
    void deleteDir(File file) { 
        if (file.isDirectory())
            for (String child : file.list())
                deleteDir(new File(file, child));
        file.delete();  // delete child file or empty directory
    }

3
private static void deleteRecursive(File dir)
{
    //Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
    if (dir.isDirectory())
    {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++)
        {
            File temp = new File(dir, children[i]);
            deleteRecursive(temp);
        }

    }

    if (dir.delete() == false)
    {
        Log.d("DeleteRecursive", "DELETE FAIL");
    }
}

2

디렉토리에서 모든 파일을 삭제하는 간단한 방법 :

호출만으로 디렉토리에서 모든 이미지를 삭제하는 일반적인 기능입니다

deleteAllImageFile (컨텍스트);

public static void deleteAllFile(Context context) {
File directory = context.getExternalFilesDir(null);
        if (directory.isDirectory()) {
            for (String fileName: file.list()) {
                new File(file,fileName).delete();
            }
        }    
    } 

2

내가 아는 가장 안전한 코드 :

private boolean recursiveRemove(File file) {
    if(file == null  || !file.exists()) {
        return false;
    }

    if(file.isDirectory()) {
        File[] list = file.listFiles();

        if(list != null) {

            for(File item : list) {
                recursiveRemove(item);
            }

        }
    }

    if(file.exists()) {
        file.delete();
    }

    return !file.exists();
}

파일이 있는지 확인하고 널을 처리하며 디렉토리가 실제로 삭제되었는지 확인


2

짧은 콜틴 버전

fun File.deleteDirectory(): Boolean {
    return if (exists()) {
        listFiles()?.forEach {
            if (it.isDirectory) {
                it.deleteDirectory()
            } else {
                it.delete()
            }
        }
        delete()
    } else false
}

1

재미를 위해 비 재귀 구현이 있습니다.

/**
 * Deletes the given folder and all its files / subfolders.
 * Is not implemented in a recursive way. The "Recursively" in the name stems from the filesystem command
 * @param root The folder to delete recursively
 */
public static void deleteRecursively(final File root) {
    LinkedList<File> deletionQueue = new LinkedList<>();
    deletionQueue.add(root);

    while(!deletionQueue.isEmpty()) {
        final File toDelete = deletionQueue.removeFirst();
        final File[] children = toDelete.listFiles();
        if(children == null || children.length == 0) {
            // This is either a file or an empty directory -> deletion possible
            toDelete.delete();
        } else {
            // Add the children before the folder because they have to be deleted first
            deletionQueue.addAll(Arrays.asList(children));
            // Add the folder again because we can't delete it yet.
            deletionQueue.addLast(toDelete);
        }
    }
}

1

(제공된 디렉토리를 포함하여 모든 하위 파일과 하위 디렉토리를 삭제하려고합니다) :

  1. 만약 File 삭제
  2. 만약 Empty Directory 삭제
  3. 인 경우 Not Empty Directory하위 디렉토리로 delete를 다시 호출하고 1 ~ 3을 반복하십시오.

예:

File externalDir = Environment.getExternalStorageDirectory()
Utils.deleteAll(externalDir); //BE CAREFUL.. Will try and delete ALL external storage files and directories

외부 저장소 디렉토리에 액세스하려면 다음 권한이 필요합니다.

(사용 ContextCompat.checkSelfPermissionActivityCompat.requestPermissions)

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

재귀 방법 :

public static boolean deleteAll(File file) {
    if (file == null || !file.exists()) return false;

    boolean success = true;
    if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
            for (File f : files) {
                if (f.isDirectory()) {
                    success &= deleteAll(f);
                }
                if (!f.delete()) {
                    Log.w("deleteAll", "Failed to delete " + f);
                    success = false;
                }
            }
        } else {
            if (!file.delete()) {
                Log.w("deleteAll", "Failed to delete " + file);
                success = false;
            }
        }
    } else {
        if (!file.delete()) {
            Log.w("deleteAll", "Failed to delete " + file);
            success = false;
        }
    }
    return success;
}

0

나는 이것의 속도에 걸렸지 만 디렉토리 구조가있는 폴더를 삭제합니다.

public int removeDirectory(final File folder) {

    if(folder.isDirectory() == true) {
        File[] folderContents = folder.listFiles();
        int deletedFiles = 0;

        if(folderContents.length == 0) {
            if(folder.delete()) {
                deletedFiles++;
                return deletedFiles;
            }
        }
        else if(folderContents.length > 0) {

            do {

                File lastFolder = folder;
                File[] lastFolderContents = lastFolder.listFiles();

                //This while loop finds the deepest path that does not contain any other folders
                do {

                    for(File file : lastFolderContents) {

                        if(file.isDirectory()) {
                            lastFolder = file;
                            lastFolderContents = file.listFiles();
                            break;
                        }
                        else {

                            if(file.delete()) {
                                deletedFiles++;
                            }
                            else {
                                break;
                            }

                        }//End if(file.isDirectory())

                    }//End for(File file : folderContents)

                } while(lastFolder.delete() == false);

                deletedFiles++;
                if(folder.exists() == false) {return deletedFiles;}

            } while(folder.exists());
        }
    }
    else {
        return -1;
    }

    return 0;

}

도움이 되었기를 바랍니다.


0
//To delete all the files of a specific folder & subfolder
public static void deleteFiles(File directory, Context c) {
    try {
        for (File file : directory.listFiles()) {
            if (file.isFile()) {
                final ContentResolver contentResolver = c.getContentResolver();
                String canonicalPath;
                try {
                    canonicalPath = file.getCanonicalPath();
                } catch (IOException e) {
                    canonicalPath = file.getAbsolutePath();
                }
                final Uri uri = MediaStore.Files.getContentUri("external");
                final int result = contentResolver.delete(uri,
                        MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
                if (result == 0) {
                    final String absolutePath = file.getAbsolutePath();
                    if (!absolutePath.equals(canonicalPath)) {
                        contentResolver.delete(uri,
                                MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
                    }
                }
                if (file.exists()) {
                    file.delete();
                    if (file.exists()) {
                        try {
                            file.getCanonicalFile().delete();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (file.exists()) {
                            c.deleteFile(file.getName());
                        }
                    }
                }
            } else
                deleteFiles(file, c);
        }
    } catch (Exception e) {
    }
}

여기도 해결책입니다. 갤러리도 새로 고칩니다.


0

그것을 해결하는 또 다른 (현대적인) 방법.

public class FileUtils {
    public static void delete(File fileOrDirectory) {
        if(fileOrDirectory != null && fileOrDirectory.exists()) {
            if(fileOrDirectory.isDirectory() && fileOrDirectory.listFiles() != null) {      
                Arrays.stream(fileOrDirectory.listFiles())
                      .forEach(FileUtils::delete);
            }
            fileOrDirectory.delete();
        }
    }
}

API 26 이후 Android에서

public class FileUtils {

    public static void delete(File fileOrDirectory)  {
        if(fileOrDirectory != null) {
            delete(fileOrDirectory.toPath());
        }
    }

    public static void delete(Path path)  {
        try {
            if(Files.exists(path)) {
                Files.walk(path)
                        .sorted(Comparator.reverseOrder())
                        .map(Path::toFile)
//                      .peek(System.out::println)
                        .forEach(File::delete);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

0

이 재귀 함수를 사용하여 작업을 수행하고 있습니다.

public static void deleteDirAndContents(@NonNull File mFile){
    if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
        for (File file : mFile.listFiles()) {
            deleteDirAndContents(file);
        }
    } else {
        mFile.delete();
    }
}

이 기능은 디렉토리인지 파일인지 확인합니다.

디렉토리가 하위 파일이 있는지 확인하면 하위 파일이 있으면 하위 파일을 전달하고 반복하여 자신을 다시 호출합니다.

파일이면 삭제합니다.

(캐시 디렉토리를 전달하여 앱 캐시를 지우는 데이 기능을 사용하지 마십시오. 캐시 디렉토리도 삭제되므로 앱이 충돌하기 때문에 ... 캐시를 지우려면이 기능을 사용하십시오. dir 당신은 그것에 전달합니다 :

public static void deleteDirContents(@NonNull File mFile){
        if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
            for (File file : mFile.listFiles()) {
                deleteDirAndContents(file);
            }
        }
    }

또는 다음을 사용하여 캐시 디렉토리인지 확인할 수 있습니다.

if (!mFile.getAbsolutePath().equals(context.getCacheDir().getAbsolutePath())) {
    mFile.delete();
}

앱 캐시를 지우는 예제 코드 :

public static void clearAppCache(Context context){
        try {
            File cache = context.getCacheDir();
            FilesUtils.deleteDirContents(cache);
        } catch (Exception e){
            MyLogger.onException(TAG, e);
        }
    }

안녕, 좋은 하루 되세요 & 코딩 : D

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.