Menghapus folder dengan python secara rekursif

203

Saya mengalami masalah dengan menghapus direktori kosong. Ini kode saya:

for dirpath, dirnames, filenames in os.walk(dir_to_search):
    //other codes

    try:
        os.rmdir(dirpath)
    except OSError as ex:
        print(ex)

Argumennya dir_to_searchadalah di mana saya melewati direktori di mana pekerjaan harus dilakukan. Direktori itu terlihat seperti ini:

test/20/...
test/22/...
test/25/...
test/26/...

Perhatikan bahwa semua folder di atas kosong. Ketika saya menjalankan script ini folder 20, 25sendiri akan dihapus! Tetapi folder 25dan 26tidak dihapus, meskipun mereka folder kosong.

Edit:

Pengecualian yang saya dapatkan adalah:

[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/29/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/28/tmp'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/26'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/25'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27'
[Errno 39] Directory not empty: '/home/python-user/shell-scripts/s3logs/test/2012/10/27/tmp'

Di mana saya membuat kesalahan?

sriram
sumber
1
apakah Anda yakin mereka tidak memiliki file tersembunyi?
Jeff
Apakah pengecualian atau traceback dicetak? Jika demikian - akan membantu jika Anda menambahkannya ke pertanyaan
Ngure Nyaga
@ Jeff: Ya ​​saya yakin. Bahkan di mesin ubuntu saya, saya mencoba rmdir /path/to/25th/foldermenghapus seluruh direktori. Yang berarti direktori itu adalah yang kosong!
sriram
2
Kemungkinan duplikat dari Bagaimana cara menghapus / menghapus folder yang tidak kosong dengan Python? dari kedua pertanyaan DAN jawabannya
Trevor Boyd Smith

Jawaban:

392

Coba shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')
Tomek
sumber
5
Apakah rmtreeseluruh direktori dihapus? Saya kira itu mirip dengan salah saturm -Rf $DIR
sriram
7
Hati-hati karena rmtree menghapus file juga. Seperti yang ditanyakan, pertanyaannya adalah bagaimana menghapus direktori KOSONG. Dokumen untuk os.walk memberikan contoh yang hampir sama persis dengan pertanyaan ini: import os for root, dirs, files in os.walk(top, topdown=False): for name in dirs: os.rmdir(os.path.join(root, name))
DaveSawyer
Dokumentasi versi Python3: docs.python.org/3/library/shutil.html#shutil.rmtree
Vladimir Oprya
27

Perilaku default os.walk()adalah berjalan dari akar ke daun. Set topdown=Falsedi os.walk()berjalan dari daun ke akar.

lqs
sumber
18

Ini pathlibpenghapus tautan direktori rekursif murni saya :

from pathlib import Path

def rmdir(directory):
    directory = Path(directory)
    for item in directory.iterdir():
        if item.is_dir():
            rmdir(item)
        else:
            item.unlink()
    directory.rmdir()

rmdir(Path("dir/"))
mitch
sumber
12

Coba rmtree()di shutildari Python perpustakaan standar

microo8
sumber
1
Apakah rmtreeseluruh direktori dihapus? Saya kira itu mirip dengan salah saturm -Rf $DIR
sriram
2
dari docs: "Hapus seluruh pohon direktori; jalur harus mengarah ke direktori (tetapi bukan tautan simbolis ke direktori). Jika ignor_errors benar, kesalahan yang dihasilkan dari penghapusan yang gagal akan diabaikan; jika salah atau dihilangkan, kesalahan seperti itu ditangani dengan memanggil pawang yang ditentukan oleh teror atau, jika itu dihilangkan, mereka menimbulkan pengecualian. "
microo8
7

lebih baik menggunakan path absolut dan hanya mengimpor fungsi rmtree from shutil import rmtree karena ini adalah paket besar, baris di atas hanya akan mengimpor fungsi yang diperlukan.

from shutil import rmtree
rmtree('directory-absolute-path')
Gajender
sumber
1
Anda kemudian akan merujuk ini sebagai rmtree(); tidakshutil.rmtree()
Kevin Murphy
4

Hanya untuk orang berikutnya yang mencari solusi micropython, ini berfungsi murni berdasarkan os (listdir, hapus, rmdir). Itu tidak lengkap (terutama dalam penanganan kesalahan) atau mewah, namun akan berfungsi dalam sebagian besar keadaan.

def deltree(target):
    print("deltree", target)
    for d in os.listdir(target):
        try:
            deltree(target + '/' + d)
        except OSError:
            os.remove(target + '/' + d)

    os.rmdir(target)
Justus Wingert
sumber
3

Perintah (diberikan oleh Tomek) tidak dapat menghapus file, jika hanya dibaca . oleh karena itu, seseorang dapat menggunakan -

import os, sys
import stat

def del_evenReadonly(action, name, exc):
    os.chmod(name, stat.S_IWRITE)
    os.remove(name)

if  os.path.exists("test/qt_env"):
    shutil.rmtree('test/qt_env',onerror=del_evenReadonly)
Monir
sumber
2
ketika mencoba kode Anda dengan folder saya sendiri yang akan dihapus, saya mendapatkan error mengatakan: NameError: name 'stat' is not defined. Bagaimana cara mendefinisikannya?
nnako
1
Modul stat mendefinisikan konstanta dan fungsi untuk menafsirkan hasil os.stat (), os.fstat () dan os.lstat (). apa yang dapat Anda coba: import os, sys from stat import *
Monir
0

Inilah solusi murni-pathlib lain , tetapi tanpa rekursi:

from pathlib import Path
from typing import Union

def del_empty_dirs(base: Union[Path, str]):
    base = Path(base)
    for p in sorted(base.glob('**/*'), reverse=True):
        if p.is_dir():
            p.chmod(0o666)
            p.rmdir()
        else:
            raise RuntimeError(f'{p.parent} is not empty!')
    base.rmdir()
pepoluan
sumber
-1

Berikut ini adalah solusi rekursif:

def clear_folder(dir):
    if os.path.exists(dir):
        for the_file in os.listdir(dir):
            file_path = os.path.join(dir, the_file)
            try:
                if os.path.isfile(file_path):
                    os.unlink(file_path)
                else:
                    clear_folder(file_path)
                    os.rmdir(file_path)
            except Exception as e:
                print(e)
Tobias Ernst
sumber
-1

Untuk pengguna Linux, Anda cukup menjalankan perintah shell dengan cara pythonic

import os
os.system("rm -r /home/user/folder_name")

di mana rmsingkatan menghapus dan -runtuk rekursif

Garvit
sumber