Как удалить/удалить папку, которая не является пустой?

При попытке удалить папку, которая не пуста, я получаю ошибку "доступ запрещен". В моей попытке я использовал следующую команду: os.remove("/folder_name").

Каков наиболее эффективный способ удаления/удаления папки/каталога, который не пуст?

Ответ 1

import shutil

shutil.rmtree('/folder_name')

Стандартная справочная библиотека: shutil.rmtree.

По дизайну rmtree выходит из строя на деревьях папок, содержащих файлы только для чтения. Если вы хотите, чтобы папка удалялась независимо от того, содержит ли она файлы только для чтения, используйте

shutil.rmtree('/folder_name', ignore_errors=True)

Ответ 2

От документы python в os.walk():

# Delete everything reachable from the directory named in 'top',
# assuming there are no symbolic links.
# CAUTION:  This is dangerous!  For example, if top == '/', it
# could delete all your disk files.
import os
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        os.remove(os.path.join(root, name))
    for name in dirs:
        os.rmdir(os.path.join(root, name))

Ответ 3

import shutil
shutil.rmtree(dest, ignore_errors=True)

Ответ 4

из python 3.4 вы можете использовать:

import pathlib

def delete_folder(pth) :
    for sub in pth.iterdir() :
        if sub.is_dir() :
            delete_folder(sub)
        else :
            sub.unlink()
    pth.rmdir() # if you just want to delete dir content, remove this line

где pth является экземпляром pathlib.Path. Хороший, но не самый быстрый.

Ответ 5

С docs.python.org:

В этом примере показано, как удалить дерево каталогов в Windows, где для некоторых файлов установлен бит только для чтения. Он использует обратный вызов onerror, чтобы очистить бит readonly и повторить попытку удаления. Любой последующий сбой будет распространяться.

import os, stat
import shutil

def remove_readonly(func, path, _):
    "Clear the readonly bit and reattempt the removal"
    os.chmod(path, stat.S_IWRITE)
    func(path)

shutil.rmtree(directory, onerror=remove_readonly)

Ответ 6

import os
import stat
import shutil

def errorRemoveReadonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
        # change the file to be readable,writable,executable: 0777
        os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  
        # retry
        func(path)
    else:
        # raiseenter code here

shutil.rmtree(path, ignore_errors=False, onerror=errorRemoveReadonly) 

Если параметр ignore_errors установлен, ошибки игнорируются; в противном случае, если установлен onerror, он вызывается для обработки ошибки с аргументами (func, path, exc_info), где func - os.listdir, os.remove или os.rmdir; path - это аргумент этой функции, которая привела к ее провалу; и exc_info - это кортеж, возвращаемый sys.exc_info(). Если ignore_errors является ложным, а onerror - None, здесь возникает исключение. Здесь вводится код

Ответ 7

если вы уверены, что хотите удалить все дерево dir, и больше не интересуетесь содержимым dir, тогда обход для всего дерева dir - это глупость... просто вызовите команду native OS из python, чтобы сделать это. Это будет быстрее, эффективнее и меньше памяти.

RMDIR c:\blah /s /q 

или * nix

rm -rf /home/whatever 

В python код будет выглядеть так.

import sys
import os

mswindows = (sys.platform == "win32")

def getstatusoutput(cmd):
    """Return (status, output) of executing cmd in a shell."""
    if not mswindows:
        return commands.getstatusoutput(cmd)
    pipe = os.popen(cmd + ' 2>&1', 'r')
    text = pipe.read()
    sts = pipe.close()
    if sts is None: sts = 0
    if text[-1:] == '\n': text = text[:-1]
    return sts, text


def deleteDir(path):
    """deletes the path entirely"""
    if mswindows: 
        cmd = "RMDIR "+ path +" /s /q"
    else:
        cmd = "rm -rf "+path
    result = getstatusoutput(cmd)
    if(result[0]!=0):
        raise RuntimeError(result[1])

Ответ 8

Основываясь на ответе kkubasik, проверьте, существует ли папка перед удалением, более надежный

import shutil
def remove_folder(path):
    # check if folder exists
    if os.path.exists(path):
         # remove if exists
         shutil.rmtree(path)
    else:
         # throw your exception to handle this special scenario
         raise XXError("your exception") 
remove_folder("/folder_name")

Ответ 9

Просто некоторые варианты python 3.5 для завершения ответов выше. (Мне бы хотелось найти их здесь).

import os
import shutil
from send2trash import send2trash # (shutil delete permanently)

Удалить папку, если пусто

root = r"C:\Users\Me\Desktop\test"   
for dir, subdirs, files in os.walk(root):   
    if subdirs == [] and files == []:
           send2trash(dir)
           print(dir, ": folder removed")

Удалить папку, если она содержит этот файл

    elif subdirs == [] and len(files) == 1: # if contains no sub folder and only 1 file 
        if files[0]== "desktop.ini" or:  
            send2trash(dir)
            print(dir, ": folder removed")
        else:
            print(dir)

удалить папку, если она содержит только файлы .srt или .txt

    elif subdirs == []: #if dir doesn’t contains subdirectory
        ext = (".srt", ".txt")
        contains_other_ext=0
        for file in files:
            if not file.endswith(ext):  
                contains_other_ext=True
        if contains_other_ext== 0:
                send2trash(dir)
                print(dir, ": dir deleted")

Удалить папку, если ее размер меньше 400 КБ:

def get_tree_size(path):
    """Return total size of files in given path and subdirs."""
    total = 0
    for entry in os.scandir(path):
        if entry.is_dir(follow_symlinks=False):
            total += get_tree_size(entry.path)
        else:
            total += entry.stat(follow_symlinks=False).st_size
    return total


for dir, subdirs, files in os.walk(root):   
    If get_tree_size(dir) < 400000:  # ≈ 400kb
        send2trash(dir)
    print(dir, "dir deleted")

Ответ 10

Если вы не хотите использовать модуль shutil, вы можете просто использовать модуль os.

from os import listdir, rmdir, remove
for i in listdir(directoryToRemove):
    os.remove(os.path.join(directoryToRemove, i))
rmdir(directoryToRemove) # Now the directory is empty of files

Ответ 11

def deleteDir(dirPath):
    deleteFiles = []
    deleteDirs = []
    for root, dirs, files in os.walk(dirPath):
        for f in files:
            deleteFiles.append(os.path.join(root, f))
        for d in dirs:
            deleteDirs.append(os.path.join(root, d))
    for f in deleteFiles:
        os.remove(f)
    for d in deleteDirs:
        os.rmdir(d)
    os.rmdir(dirPath)

Ответ 12

Для простоты вы можете использовать команду os.system:

import os
os.system("rm -rf dirname")

Как очевидно, он фактически вызывает системный терминал для выполнения этой задачи.

Ответ 13

Чтобы удалить папку, даже если она может не существовать (избегая условия гонки в ответ Чарльза Чоу), но все еще есть ошибки, когда другие вещи идут не так (например, проблемы с разрешением, ошибка чтения диска, файл не является каталогом)

Для Python 3.x:

import shutil

def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, FileNotFoundError):
        return
    raise except_instance

shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

Код Python 2.7 почти тот же:

import shutil
import errno

def ignore_absent_file(func, path, exc_inf):
    except_instance = exc_inf[1]
    if isinstance(except_instance, OSError) and \
        except_instance.errno == errno.ENOENT:
        return
    raise except_instance

shutil.rmtree(dir_to_delete, onerror=ignore_absent_file)

Ответ 14

С os.walk я бы предложил решение, которое состоит из 3 однострочных вызовов Python:

python -c "import sys; import os; [os.chmod(os.path.join(rs,d), 0o777) for rs,ds,fs in os.walk(_path_) for d in ds]"
python -c "import sys; import os; [os.chmod(os.path.join(rs,f), 0o777) for rs,ds,fs in os.walk(_path_) for f in fs]"
python -c "import os; import shutil; shutil.rmtree(_path_, ignore_errors=False)"

Первый скрипт chmod для всех подкаталогов, второй скрипт chmod для всех файлов. Затем третий сценарий удаляет все без препятствий.

Я проверил это из "Shell Script" в задании Jenkins (я не хотел сохранять новый скрипт Python в SCM, поэтому искал однострочное решение), и он работал для Linux и Windows.

Ответ 15

Десять лет спустя и с использованием Python 3.7 и Linux все еще существуют разные способы сделать это:

import subprocess
from pathlib import Path

#using pathlib.Path
path = Path('/path/to/your/dir')
subprocess.run(["rm", "-rf", str(path)])

#using strings
path = "/path/to/your/dir"
subprocess.run(["rm", "-rf", path])

По сути, он использует модуль подпроцесса Python для запуска bash-скрипта $ rm -rf '/path/to/your/dir как если бы вы использовали терминал для выполнения той же задачи. Это не полностью Python, но это делается.

Причина, по которой я включил пример pathlib.Path заключается в том, что, по моему опыту, он очень полезен при работе со многими путями, которые меняются. Дополнительные этапы импорта модуля pathlib.Path и преобразования конечных результатов в строки часто обходятся мне дешевле из-за времени разработки. Было бы удобно, если бы Path.rmdir() поставлялся с опцией arg для явной обработки непустых директорий.

Ответ 16

Я хотел бы добавить "чистый путь пути":

from pathlib import Path
from typing import Union

def del_dir(target: Union[Path, str], only_if_empty: bool = False):
    target = Path(target).expanduser()
    assert target.is_dir()
    for p in sorted(target.glob('**/*'), reverse=True):
        if not p.exists():
            continue
        p.chmod(0o666)
        if p.is_dir():
            p.rmdir()
        else:
            if only_if_empty:
                raise RuntimeError(f'{p.parent} is not empty!')
            p.unlink()
    target.rmdir()

Это основано на том факте, что Path можно заказать, и более длинные пути всегда будут сортироваться по более коротким, как и str. Поэтому каталоги будут предшествовать файлам. Если мы перевернем сортировку, то файлы будут находиться перед соответствующими контейнерами, поэтому мы можем просто отсоединить /rmdir их один за другим за один проход.

Преимущества:

  • Он НЕ полагается на внешние двоичные файлы: все использует модули с питанием от батарей Python (Python> = 3.6)
  • Это быстро и эффективно использует память: нет рекурсивного стека, нет необходимости запускать подпроцесс
  • Он кроссплатформенный (по крайней мере, то, что pathlib обещает в Python 3.6; выше не указано, что операция не выполняется в Windows)
  • При необходимости можно вести очень детальную регистрацию, например, регистрировать каждое удаление, как оно происходит.

Ответ 17

Я нашел очень простой способ удалить любую папку (даже НЕ пустую) или файл в ОС Windows.

os.system('powershell.exe  rmdir -r D:\workspace\Branches\*%s* -Force' %CANDIDATE_BRANCH)

Ответ 18

Для Windows, если каталог не пустой, и у вас есть файлы только для чтения, или вы получаете ошибки, такие как

  • Access is denied
  • The process cannot access the file because it is being used by another process

Попробуйте это, os.system('rmdir/S/Q "{}"'.format(directory))

Это эквивалентно для rm -rf в Linux/Mac.