Xóa các thư mục trong python một cách đệ quy


203

Tôi đang gặp vấn đề với việc xóa các thư mục trống. Đây là mã của tôi:

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

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

Đối số dir_to_searchlà nơi tôi đi qua thư mục nơi công việc cần được thực hiện. Thư mục đó trông như thế này:

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

Lưu ý rằng tất cả các thư mục trên đều trống. Khi tôi chạy kịch bản này các thư mục 20, 25một mình bị xóa! Nhưng các thư mục 2526không bị xóa, mặc dù chúng là các thư mục trống.

Biên tập:

Ngoại lệ mà tôi nhận được là:

[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'

Tôi đang phạm sai lầm ở đâu?


1
bạn có chắc là họ không có tập tin ẩn?
Jeff

Là một ngoại lệ hoặc truy nguyên được in? Nếu vậy - sẽ rất hữu ích nếu bạn thêm câu hỏi đó vào câu hỏi
Ngure Nyaga

@Jeff: Vâng, tôi chắc chắn. Trong thực tế, trong máy ubfox của tôi, tôi đã thử rmdir /path/to/25th/folderxóa toàn bộ thư mục. Có nghĩa là thư mục đó là một cái trống!
sriram

2
Có thể trùng lặp Làm thế nào để tôi xóa / xóa một thư mục không trống với Python? của cả hai câu hỏi VÀ câu trả lời
Trevor Boyd Smith

Câu trả lời:


392

Hãy thử shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')

5
rmtreexóa toàn bộ thư mục? Tôi đoán nó tương tự như mộtrm -Rf $DIR
sriram

7
Hãy cẩn thận vì rmtree cũng xóa các tập tin. Khi được hỏi, câu hỏi là làm thế nào để xóa các thư mục EMPTY. Các tài liệu cho os.walk đưa ra một ví dụ gần như khớp chính xác với câu hỏi này: import os for root, dirs, files in os.walk(top, topdown=False): for name in dirs: os.rmdir(os.path.join(root, name))
DaveSawyer


27

Hành vi mặc định của os.walk()là đi bộ từ gốc đến lá. Đặt topdown=Falsetrong os.walk()để đi bộ từ lá đến gốc.


18

Đây là pathlibthư mục đệ quy thuần túy của tôi unlinker:

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/"))

12

Hãy thử rmtree()trong shutiltừ thư viện chuẩn của Python


1
rmtreexóa toàn bộ thư mục? Tôi đoán nó tương tự như mộtrm -Rf $DIR
sriram

2
từ docs: "Xóa toàn bộ cây thư mục; đường dẫn phải trỏ đến thư mục (nhưng không phải là liên kết tượng trưng đến thư mục). Nếu ign_errors là đúng, các lỗi do xóa không thành công sẽ bị bỏ qua; nếu sai hoặc bỏ qua, các lỗi đó sẽ được xử lý bằng cách gọi một trình xử lý được chỉ định bởi onerror hoặc, nếu điều đó bị bỏ qua, họ sẽ đưa ra một ngoại lệ. "
microo8

7

tốt hơn là sử dụng đường dẫn tuyệt đối và chỉ nhập hàm rmtree from shutil import rmtree vì đây là gói lớn, dòng trên sẽ chỉ nhập hàm được yêu cầu.

from shutil import rmtree
rmtree('directory-absolute-path')

1
Sau đó, bạn sẽ tham khảo điều này như rmtree(); khôngshutil.rmtree()
Kevin Murphy

4

Chỉ cần cho anh chàng tiếp theo tìm kiếm một giải pháp micropython, điều này hoạt động hoàn toàn dựa trên os (listdir, remove, rmdir). Nó không hoàn chỉnh (đặc biệt là trong lỗi thủ công) cũng không ưa thích, tuy nhiên nó sẽ hoạt động trong hầu hết các trường hợp.

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)

3

Lệnh (được đưa ra bởi Tomek) không thể xóa một tệp, nếu nó chỉ được đọc . do đó, người ta có thể sử dụng -

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)

2
Khi thử mã của bạn với thư mục của riêng tôi bị xóa, tôi gặp lỗi thông báo : NameError: name 'stat' is not defined. Làm thế nào nó đã được xác định?
nnako

1
Mô-đun stat xác định các hằng và hàm để diễn giải kết quả của os.stat (), os.fstat () và os.lstat (). những gì bạn có thể thử: nhập os, sys từ stat nhập *
Monir

0

Đây là một giải pháp pathlib thuần túy khác , nhưng không có đệ quy:

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()

-1

Đây là một giải pháp đệ quy:

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)

-1

Đối với người dùng Linux, bạn chỉ cần chạy lệnh shell theo cách pythonic

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

nơi rmviết tắt của từ bỏ-rcho đệ quy

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.