Удаление папок в Python рекурсивно

204

У меня проблема с удалением пустых каталогов. Вот мой код:

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'

Где я делаю ошибку?

Sriram
источник
1
Вы уверены, что у них нет скрытых файлов?
Джефф
Напечатано ли исключение или трассировка? Если это так - было бы
полезно,
@Джефф: Да, я уверен. На самом деле в моей машине с Ubuntu я пытался rmdir /path/to/25th/folderудалить весь каталог. Что означает, что каталог пустой!
Шрирам
2
Возможный дубликат Как мне удалить / удалить папку, которая не пуста в Python? вопроса и ответа
Тревор Бойд Смит

Ответы:

393

Попробуй shutil.rmtree:

import shutil
shutil.rmtree('/path/to/your/dir/')
Томек
источник
5
Удаляется ли rmtreeвесь каталог? Я думаю, что это похоже на одинrm -Rf $DIR
Шрирам
7
Будьте осторожны, так как rmtree тоже удаляет файлы. Как и было задано, вопрос заключался в том, как удалить пустые каталоги. Документы для 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
Документация по версии Python3: docs.python.org/3/library/shutil.html#shutil.rmtree
Владимир Опря
27

Поведение по умолчанию os.walk()состоит в том, чтобы идти от корня до листа. Набор topdown=Falseв os.walk()идти от листьев к корню.

коды LQ
источник
18

Вот мой чистый pathlibрекурсивный каталоги 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

Попробуйте rmtree()в shutilстандартных библиотеках Python

microo8
источник
1
Удаляется ли rmtreeвесь каталог? Я думаю, что это похоже на одинrm -Rf $DIR
Шрирам
2
из документов: "Удалить все дерево каталогов; путь должен указывать на каталог (но не символическую ссылку на каталог). Если значение параметра ignore_errors равно true, ошибки, возникшие в результате неудачного удаления, будут игнорироваться; если false или пропущено, такие ошибки обрабатываются вызывая обработчик, указанный в onerror, или, если он пропущен, они вызывают исключение. "
microo8
7

Лучше использовать абсолютный путь и импортировать только функцию rmtree, так from shutil import rmtree как это большой пакет, указанная выше строка импортирует только требуемую функцию.

from shutil import rmtree
rmtree('directory-absolute-path')
Gajender
источник
1
Затем вы бы сослаться на это как rmtree(); нетshutil.rmtree()
Кевин Мерфи
4

Просто для следующего парня, который ищет решение для микропифона, это работает исключительно на основе os (listdir, remove, 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

Команда (данная Tomek) не может удалить файл, если он только для чтения . следовательно, можно использовать -

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
источник
2
при попытке кода с моей папки для удаления, я получаю сообщение об ошибке сказав: NameError: name 'stat' is not defined. Как это было определено?
nnako
1
Модуль stat определяет константы и функции для интерпретации результатов os.stat (), os.fstat () и os.lstat (). что вы можете попробовать: импортировать os, sys из 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()
pepoluan
источник
-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для рекурсивного

Garvit
источник