it-swarm.com.de

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

Beim Versuch, einen nicht leeren Ordner zu löschen, wird die Fehlermeldung "Zugriff verweigert" angezeigt. Ich habe bei meinem Versuch den folgenden Befehl verwendet: os.remove("/folder_name")

Was ist die effektivste Methode zum Entfernen/Löschen eines nicht leeren Ordners/Verzeichnisses?

717
Amara
import shutil

shutil.rmtree('/folder_name')

Standard-Bibliotheksreferenz: shutil.rmtree .

rmtree schlägt in Ordnern, die schreibgeschützte Dateien enthalten, fehl. Wenn der Ordner unabhängig davon, ob er schreibgeschützte Dateien enthält, gelöscht werden soll, verwenden Sie

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

Von den Python-Dokumenten am 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))
123
kkubasik
import shutil
shutil.rmtree(dest, ignore_errors=True)
99
Siva Mandadi

ab Python 3.4 können Sie Folgendes verwenden:

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

dabei ist pth eine pathlib.Path-Instanz. Schön, aber vielleicht nicht der Schnellste.

15
yota
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 ein Fehler festgelegt ist, wird er aufgerufen, um den Fehler mit Argumenten (func, path, exc_info) zu behandeln, wobei func os.listdir, os.remove oder os.rmdir ist. Pfad ist das Argument für diese Funktion, die dazu geführt hat, dass sie fehlgeschlagen ist. und exc_info ist ein von sys.exc_info () zurückgegebenes Tuple. Wenn ignore_errors "false" und "onerror" None ist, wird hier eine Ausnahme ausgelöst

7
RongyanZheng

wenn Sie sicher sind, dass Sie den gesamten Verzeichnisbaum löschen möchten, und sich nicht mehr für den Inhalt des Verzeichnisses interessieren, ist das Crawlen für den gesamten Verzeichnisbaum Dummheit. Rufen Sie dazu einfach den systemeigenen Betriebssystembefehl von Python auf. Es wird schneller, effizienter und sparsamer. 

RMDIR c:\blah /s /q 

oder * nix 

rm -rf /home/whatever 

In Python wird der Code folgendermaßen aussehen.

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])
5
P M

Von docs.python.org :

In diesem Beispiel wird gezeigt, wie eine Verzeichnisstruktur unter Windows mit .__ entfernt wird. Für einige Dateien ist das schreibgeschützte Bit gesetzt. Es verwendet den Onerror callback, um das readonly-Bit zu löschen und das Entfernen erneut auszuführen. Irgendein nachfolgender Fehler wird sich ausbreiten.

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)
5
Dave Chandler

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 falls 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ösche auch 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")

Ordner löschen, wenn die Größe weniger als 400 kb beträgt:

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

Basierend auf der Antwort von kkubasik, überprüfen Sie vor dem Entfernen, ob der Ordner vorhanden ist

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")
4
Charles Chow

Wenn Sie das Modul shutil nicht verwenden möchten, können Sie das Modul os verwenden.

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
3
Byron Filer
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)
2
amazingthere

Sie können den Befehl os.system zur Vereinfachung verwenden:

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

Wie offensichtlich, ruft es tatsächlich ein Systemendgerät auf, um diese Aufgabe auszuführen.

2
user5449023

Ich möchte einen "pure pathlib" -Ansatz hinzufügen:

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

Dies beruht auf der Tatsache, dass Path bestellt werden kann und längere Pfade immer nach kürzeren Pfaden sortiert werden, genau wie str. Daher stehen Verzeichnisse vor Dateien. Wenn wir umkehren , werden die Dateien vor ihren jeweiligen Containern abgelegt, sodass wir sie einfach nacheinander trennen können eins mit einem Durchgang.

Leistungen:

  • Es ist NICHT auf externe Binärdateien angewiesen: Alles verwendet Pythons batteriebetriebene Module (Python> = 3.6).
  • Es ist schnell und speichereffizient: Kein Rekursionsstapel, kein Start eines Unterprozesses erforderlich
  • Es ist plattformübergreifend (zumindest verspricht dies pathlib in Python 3.6; es wurde oben kein Vorgang angegeben, der nicht unter Windows ausgeführt werden soll).
  • Bei Bedarf kann eine sehr detaillierte Protokollierung durchgeführt werden, z. B. jede Löschung nacheinander protokollieren.
1
pepoluan

Mit os.walk würde ich die Lösung vorschlagen, die aus drei Ein-Liner-Python-Aufrufen besteht:

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

Das erste Skript chmod alle Unterverzeichnisse, das zweite Skript chmod alle Dateien. Dann entfernt das dritte Skript alles ohne Hindernisse.

Ich habe dies aus dem "Shell Script" in einem Jenkins-Job getestet (ich wollte kein neues Python-Skript in SCM speichern, deshalb nach einer einzeiligen Lösung gesucht) und es funktionierte für Linux und Windows.

1

Einen Ordner löschen, auch wenn er möglicherweise nicht existiert (Vermeidung der Race-Bedingung in Charles Chows Antwort ), aber trotzdem Fehler auftreten, wenn andere Dinge schief laufen (z. B. Berechtigungsprobleme, Fehler beim Lesen der Festplatte, Datei ist kein Verzeichnis)

Für 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)

Der Python 2.7-Code ist fast derselbe:

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)
1
Eponymous

Zehn Jahre später und bei Verwendung von Python 3.7 und Linux gibt es noch verschiedene Möglichkeiten, dies zu tun:

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

Im Wesentlichen verwenden Sie das Subprozess-Modul von Python, um das Bash-Skript $ rm -rf '/path/to/your/dir so auszuführen, als würden Sie das Terminal verwenden, um dieselbe Aufgabe auszuführen. Es ist nicht vollständig Python, aber es schafft es. 

Der Grund, aus dem ich das pathlib.Path-Beispiel aufgenommen habe, ist, dass es meiner Erfahrung nach sehr nützlich ist, wenn es um viele Pfade geht, die sich ändern. Die zusätzlichen Schritte des Importierens des pathlib.Path-Moduls und der Konvertierung der Endergebnisse in Strings sind für mich oft mit geringeren Entwicklungskosten verbunden. Es wäre praktisch, wenn Path.rmdir() mit einer arg-Option ausgestattet wäre, um nicht leere Verzeichnisse explizit zu behandeln.

0
RodogInfinite

Wenn das Verzeichnis unter Windows nicht leer ist und Sie schreibgeschützte Dateien haben oder Fehler wie erhalten

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

Versuchen Sie dies, os.system('rmdir /S /Q "{}"'.format(directory))

Es ist äquivalent für rm -rf unter Linux/Mac.

0
Kartik Raj

Ich habe einen sehr einfachen Weg gefunden, um alle Ordner (auch nicht leer) oder Dateien unter WINDOWS OS zu löschen.

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