Видалення папок у python рекурсивно


202

У мене виникають проблеми зі видаленням порожніх каталогів. Ось мій код:

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

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

Аргумент dir_to_search- це те, де я передаю каталог, де потрібно виконати роботу. Цей каталог виглядає приблизно так:

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

Зауважте, що всі вищевказані папки порожні. Коли я запускаю цей скрипт папки 20, в 25поодинці буде знищений! Але папка 25і 26не видаляється, навіть якщо вони порожні папки.

Редагувати:

Виняток, який я отримую, є:

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

Де я помиляюся?


1
Ви впевнені, що у них немає прихованих файлів?
Джефф

Чи надруковано виняток чи прослідкування? Якщо так - допоможе, якщо ви додасте це до питання
Ngure Nyaga

@Jeff: Так, я впевнений. Насправді на моїй машині ubuntu я спробував rmdir /path/to/25th/folderвидалити весь каталог. Що означає, що цей каталог порожній!
срірам

Відповіді:


392

Спробуйте shutil.rmtree:

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

5
Чи rmtreeвидалено весь каталог? Я здогадуюсь це схоже на тойrm -Rf $DIR
sriram

7
Будьте уважні, оскільки rmtree також видаляє файли. На його запитання було питання, як видалити каталоги EMPTY. Документи для os.walk наводять приклад, який майже точно відповідає цьому питанню: 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

Типова поведінка os.walk()- ходити від кореня до листка. Набір topdown=Falseв os.walk()йти від листя до кореня.


18

Ось мій чистий pathlibрекурсивний розв'язувач каталогів:

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

Спробуйте rmtree()в shutilстандартній бібліотеці Python


1
Чи rmtreeвидалено весь каталог? Я здогадуюсь це схоже на тойrm -Rf $DIR
sriram

2
from docs: "Видалити ціле дерево каталогів; шлях повинен вказувати на каталог (але не символічне посилання на каталог). Якщо true_errors істинно, помилки, отримані в результаті невдалих видалень, будуть ігноруватися; якщо помилкові чи пропущені, такі помилки обробляються зателефонувавши до обробника, вказаного onerror, або, якщо це пропущено, вони створюють виняток. "
microo8

7

краще використовувати абсолютний шлях та імпортувати лише функцію rmtree, from shutil import rmtree оскільки це великий пакет, наведений вище рядок буде імпортувати лише необхідну функцію.

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

1
Потім ви б посилалися на це як rmtree(); ніshutil.rmtree()
Кевін Мерфі

4

Просто для наступного хлопця, який шукає мікропітонне рішення, це працює виключно на основі os (listdir, delete, rmdir). Це не є повноцінним (особливо в роботі з помилками) і не фантастичним, але воно буде працювати в більшості обставин.

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

Команда (дана Томеком) не може видалити файл, якщо він читається тільки . тому можна використовувати -

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
при спробі видалення вашого коду з власної папки я отримую помилку: " NameError: name 'stat' is not defined. Як це було визначено?
nnako

1
Модуль stat визначає константи та функції інтерпретації результатів os.stat (), os.fstat () та os.lstat (). що ви можете спробувати: import os, sys from stat import *
Monir

0

Ось ще одне рішення з чистою доріжкою , але без рекурсії:

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

Ось рекурсивне рішення:

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

Для користувачів Linux можна просто запустити команду оболонки пітонічним способом

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

де rmпозначає Витягніть і -rдля рекурсивного

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.