1114 Stimmen

Wie entferne/lösche ich einen Ordner, der nicht leer ist?

Ich erhalte die Fehlermeldung "Zugriff verweigert", wenn ich versuche, einen Ordner zu löschen, der nicht leer ist. Ich habe bei meinem Versuch den folgenden Befehl verwendet: os.remove("/folder_name") .

Wie lässt sich ein Ordner/Verzeichnis, das nicht leer ist, am effektivsten entfernen/löschen?

13voto

Charles Chow Punkte 977

Basierend auf der Antwort von kkubasik, prüfen Sie, ob der Ordner existiert, bevor Sie ihn entfernen, das ist robuster

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

9voto

RY_ Zheng Punkte 2253
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) 

Wenn ignore_errors gesetzt ist, werden Fehler ignoriert; andernfalls, wenn onerror gesetzt ist, wird es aufgerufen, um den Fehler mit Argumenten (func, path, exc_info) zu behandeln, wobei func os.listdir, os.remove oder os.rmdir ist; path ist das Argument der Funktion, das den Fehler verursacht hat; und exc_info ist ein Tupel, das von sys.exc_info() zurückgegeben wird. Wenn ignore_errors false und onerror None ist, wird eine Exception ausgelöst.enter code here

8voto

pepoluan Punkte 5313

Ich würde gerne einen "reinen Pathlib"-Ansatz hinzufügen:

from pathlib import Path
from typing import Union

def del_dir(target: Union[Path, str], only_if_empty: bool = False):
    """
    Delete a given directory and its subdirectories.

    :param target: The directory to delete
    :param only_if_empty: Raise RuntimeError if any file is found in the tree
    """
    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()

Dies beruht auf der Tatsache, dass Path ist ordnbar, und längere Pfade werden immer nach kürzeren Pfaden sortiert, genau wie str . Daher werden Verzeichnisse vor Dateien angezeigt. Wenn wir umkehren der Sortierung stehen die Dateien dann vor ihren jeweiligen Containern, so dass wir sie einfach nacheinander in einem Durchgang entlinkt/umgeleitet werden können.

Vorteile:

  • Es verlässt sich NICHT auf externe Binärdateien: alles verwendet Pythons in Batterien enthaltene Module (Python >= 3.6)
    • Das bedeutet, dass er nicht wiederholt einen neuen Unterprozess starten muss, um die Verknüpfung zu lösen.
  • Es ist ziemlich schnell und einfach; Sie müssen keine eigene Rekursion implementieren
  • Es ist plattformübergreifend (zumindest ist es das, was pathlib verspricht in Python 3.6; keine Operation oben angegeben, um nicht auf Windows laufen)
  • Bei Bedarf kann man eine sehr granulare Protokollierung vornehmen, z. B. jede Löschung protokollieren, wenn sie geschieht.

7voto

P M Punkte 817

Wenn Sie sicher sind, dass Sie den gesamten Verzeichnisbaum löschen wollen und nicht mehr am Inhalt des Verzeichnisses interessiert sind, dann ist das Durchsuchen des gesamten Verzeichnisbaums eine Dummheit... rufen Sie einfach den nativen OS-Befehl aus Python auf, um das zu tun. Das ist schneller, effizienter und verbraucht weniger Speicher.

RMDIR c:\blah /s /q 

oder *nix

rm -rf /home/whatever 

In Python sieht der Code wie folgt aus:.

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

6voto

JinSnow Punkte 1323

Nur einige Python 3.5 Optionen, um die obigen Antworten zu vervollständigen. (Ich hätte sie gerne hier gefunden).

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

Ordner löschen, wenn leer

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

Löschen Sie auch den Ordner, wenn er diese Datei enthält

    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)

Ordner löschen, wenn er nur .srt- oder .txt-Dateien enthält

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

Löschen Sie den Ordner, wenn er weniger als 400kb groß ist:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X