Wie lösche ich den Inhalt eines Ordners?


469

Wie kann ich den Inhalt eines lokalen Ordners in Python löschen?

Das aktuelle Projekt ist für Windows, aber ich würde gerne * nix auch sehen.


2
für * nix um ehrlich zu sein würde ich nur verwendenos.system('rm -rf folder')
Tilak Maddy

Antworten:


442
import os, shutil
folder = '/path/to/folder'
for filename in os.listdir(folder):
    file_path = os.path.join(folder, filename)
    try:
        if os.path.isfile(file_path) or os.path.islink(file_path):
            os.unlink(file_path)
        elif os.path.isdir(file_path):
            shutil.rmtree(file_path)
    except Exception as e:
        print('Failed to delete %s. Reason: %s' % (file_path, e))

4
Wenn Sie mit einem sehr großen Verzeichnis und insbesondere einem Netzwerkverzeichnis unter Windows arbeiten und die Umgebung steuern können, in der dieses Programm ausgeführt wird, ist es möglicherweise sinnvoll, anstelle von Py3.5 die Funktion "os.scandir (Ordner)" zu verwenden listdir. Die Syntax ist danach ganz anders, aber ziemlich einfach zu implementieren. gerne posten, wenn andere wollen.
Michael Scott Cuthbert

Ich bekomme eine Pylint-Warnung mit except Exception as e:der Aufschrift W0703: Catching too general exception Exception. Gibt es eine spezifischere Ausnahme zu fangen oder sollte ich sie ignorieren?
John Hany

7
@ JohnHany, ich glaube du willst OSError fangen.
MikeB

246

Sie können dies einfach tun:

import os
import glob

files = glob.glob('/YOUR/PATH/*')
for f in files:
    os.remove(f)

Sie können natürlich einen anderen Filter in Ihrem Pfad verwenden, zum Beispiel: /YOU/PATH/*.txt, um alle Textdateien in einem Verzeichnis zu entfernen.


12
@Blueicefield listet *keine versteckten Dateien auf, wir sollten auch hinzufügenglob.glob('path/.*)
satoru

5
Obwohl es mir einfacher erscheint, die Liste der Dateien zu löschen:import sh; sh.rm(files)
Robin Winslow

2
Obwohl import sh; sh.rm(files)es hübscher aussieht, treten Probleme auf, wenn sich mehr als 1024 Dateien im Verzeichnis befinden.
Eugene

235

Sie können den Ordner selbst sowie den gesamten Inhalt folgendermaßen löschen shutil.rmtree:

import shutil
shutil.rmtree('/path/to/folder')
shutil.rmtree(path, ignore_errors=False, onerror=None)


Löschen Sie einen gesamten Verzeichnisbaum. Der Pfad muss auf ein Verzeichnis verweisen (jedoch nicht auf einen symbolischen Link zu einem Verzeichnis). Wenn ignore_errors true ist, werden Fehler, die aus fehlgeschlagenen Entfernungen resultieren, ignoriert. Wenn sie falsch sind oder weggelassen werden, werden solche Fehler durch Aufrufen eines von onerror angegebenen Handlers behandelt, oder wenn dies weggelassen wird, lösen sie eine Ausnahme aus.


270
Dadurch werden nicht nur der Inhalt, sondern auch der Ordner selbst gelöscht. Ich denke nicht, dass es das ist, was die Frage stellt.
Iker Jimenez

3
Ich denke es ist eine gute Antwort. Warum löschen Sie nicht einfach den Inhalt und den Ordner und erstellen den Ordner neu?
CSSNDRX

42
Weil das neue und das alte Verzeichnis nicht dasselbe sind. Wenn also ein Programm im Verzeichnis sitzt und auf Dinge wartet, wird der Teppich darunter herausgezogen.
Mike Cooper

30
Erstellen Sie einfach das Verzeichnis nach neu rmtree. Gefällt os.makedirs(dir)
Iulius Curt

3
@IuliusCurt nein, ich habe ein Verzeichnis in RAM gemountet, das ich leeren muss, und leider kann ich es nicht einfach löschen und dann neu erstellen:OSError: [Errno 16] Device or resource busy
Arnaud P

80

Ich habe Mhawkes Antwort erweitert und dies implementiert. Es entfernt den gesamten Inhalt eines Ordners, jedoch nicht den Ordner selbst. Getestet unter Linux mit Dateien, Ordnern und symbolischen Links, sollte auch unter Windows funktionieren.

import os
import shutil

for root, dirs, files in os.walk('/path/to/folder'):
    for f in files:
        os.unlink(os.path.join(root, f))
    for d in dirs:
        shutil.rmtree(os.path.join(root, d))

1
Warum "gehen" und nicht nur Ordnerinhalte auflisten?
Don

2
Dies ist die richtige Antwort, wenn Sie auch Verzeichnisse löschen möchten. walkwird verwendet, um Verzeichnisse gegen Dateien aufzuteilen, die unterschiedlich behandelt werden müssen. Sie können auch verwenden os.listdir, müssen jedoch manuell prüfen, ob jeder Eintrag ein Verzeichnis oder eine Datei ist.
Dkamins

7
Dies ist nah, aber sowohl os.walk als auch shutil.rmtree sind rekursiv. os.walk ist nicht erforderlich, da Sie nur die Dateien und Verzeichnisse auf der obersten Ebene innerhalb des zu bereinigenden Verzeichnisses benötigen. Verwenden Sie einfach eine if-Anweisung für Elemente in os.listdir, um festzustellen, ob es sich bei jeder um eine Datei oder ein Verzeichnis handelt. Verwenden Sie dann remove / unlink bzw. rmtree.
Matthew Alpert

1
@MatthewAlpert Beachten Sie jedoch, dass os.walkdies hier nicht wiederholt wird, da ein Generator zurückgegeben wird, der nur dann rekursiv in Unterverzeichnisse schaut, wenn Sie versuchen, ihn voranzutreiben, und bis Sie Ihre erste Iteration dieser Schleife durchgeführt haben, gibt es keine Unterverzeichnisse links zu sehen. Im Wesentlichen os.walkwird hier nur eine alternative Methode zur Unterscheidung von Ordnern der obersten Ebene von Dateien der obersten Ebene verwendet. Die Rekursion wird nicht verwendet und wir zahlen keine Leistungskosten dafür. Es ist jedoch exzentrisch, und ich stimme zu, dass der von Ihnen vorgeschlagene Ansatz einfach deshalb besser ist, weil er expliziter und lesbarer ist.
Mark Amery

47

Das Verwenden rmtreeund Neuerstellen des Ordners könnte funktionieren, aber beim Löschen und sofortigen Neuerstellen von Ordnern auf Netzwerklaufwerken sind Fehler aufgetreten.

Die vorgeschlagene Lösung mit walk funktioniert nicht, da sie rmtreezum Entfernen von Ordnern verwendet wird, und versucht dann möglicherweise, os.unlinkdie Dateien zu verwenden, die sich zuvor in diesen Ordnern befanden. Dies verursacht einen Fehler.

Die veröffentlichte globLösung versucht auch, nicht leere Ordner zu löschen, was zu Fehlern führt.

Ich schlage vor, Sie verwenden:

folder_path = '/path/to/folder'
for file_object in os.listdir(folder_path):
    file_object_path = os.path.join(folder_path, file_object)
    if os.path.isfile(file_object_path) or os.path.islink(file_object_path):
        os.unlink(file_object_path)
    else:
        shutil.rmtree(file_object_path)

1
Ihre Lösung löst auch einen Fehler aus, wenn ein Symlink zu einem anderen Verzeichnis vorhanden ist.
Blueicefield

@Blueicefield - Können Sie ein Beispiel angeben? Ich habe unter Linux mit einer verknüpften Datei und einem Ordner getestet und konnte noch keinen Fehler verursachen.
Jgoeders

@jgoeders - Wenn ein Symlink zu einem Verzeichnis vorhanden ist, os.path.isfile()wird dieser zurückgegeben False(da er auf Symlinks folgt), und Sie werden am Ende shutil.rmtree()einen Symlink aufrufen , der ausgelöst wird OSError("Cannot call rmtree on a symbolic link").
Rockallite

1
@ Rockallite durch Scheck zu islink behoben
kevinf

1
Außerdem: @kevinf ist richtig, um darauf hinzuweisen, dass islinkhier eine Überprüfung erforderlich ist, um Symlinks zu Verzeichnissen korrekt zu behandeln. Ich habe der akzeptierten Antwort einen solchen Scheck hinzugefügt.
Mark Amery

20

Diese:

  • entfernt alle symbolischen Links
    • tote Links
    • Links zu Verzeichnissen
    • Links zu Dateien
  • Entfernt Unterverzeichnisse
  • entfernt das übergeordnete Verzeichnis nicht

Code:

for filename in os.listdir(dirpath):
    filepath = os.path.join(dirpath, filename)
    try:
        shutil.rmtree(filepath)
    except OSError:
        os.remove(filepath)

Wie bei vielen anderen Antworten wird hierdurch nicht versucht, die Berechtigungen anzupassen, um das Entfernen von Dateien / Verzeichnissen zu ermöglichen.


15

Als Oneliner:

import os

# Python 2.7
map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )

# Python 3+
list( map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) ) )

Eine robustere Lösung, die auch Dateien und Verzeichnisse berücksichtigt, wäre (2.7):

def rm(f):
    if os.path.isdir(f): return os.rmdir(f)
    if os.path.isfile(f): return os.unlink(f)
    raise TypeError, 'must be either file or directory'

map( rm, (os.path.join( mydir,f) for f in os.listdir(mydir)) )

1
Für große Operationen kann die Verwendung des Generators map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
geringfügig

Beim tatsächlichen Versuch, dies zu verwenden, wurde erkannt, dass das Kartenobjekt durchlaufen werden muss, sodass ein Aufruf der Liste (oder etwas, das iteriert) erforderlich ist, wie list(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
z.

Das erste ist in der Antwort enthalten, das zweite ergibt für mich keinen Sinn. Warum sollten Sie über eine Funktion iterieren, die einer iterablen Funktion zugeordnet ist? Map macht das.
Fmonegaglia

1
In Python3, müssen Sie wickeln mapin list tatsächlich Iterierte. Siehe http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit

Dieser wird definitiv nicht funktionieren, wenn 'mydir' mindestens einen Ordner enthält, da die
Verknüpfung

14

Anmerkungen: Falls jemand meine Antwort abgelehnt hat, muss ich hier etwas erklären.

  1. Jeder mag kurze und einfache Antworten. Manchmal ist die Realität jedoch nicht so einfach.
  2. Zurück zu meiner Antwort. Ich weiß, shutil.rmtree()könnte verwendet werden, um einen Verzeichnisbaum zu löschen. Ich habe es oft in meinen eigenen Projekten verwendet. Sie müssen jedoch wissen, dass das Verzeichnis selbst auch von gelöscht wirdshutil.rmtree() . Während dies für einige akzeptabel sein mag, ist es keine gültige Antwort zum Löschen des Inhalts eines Ordners (ohne Nebenwirkungen) .
  3. Ich zeige Ihnen ein Beispiel für die Nebenwirkungen. Angenommen, Sie haben ein Verzeichnis mit benutzerdefinierten Eigentümer- und Modusbits, in dem viele Inhalte vorhanden sind. Dann löschen Sie es mit shutil.rmtree()und erstellen es mit neu os.mkdir(). Außerdem erhalten Sie ein leeres Verzeichnis mit Standard- (geerbten) Eigentümer- und Modusbits. Während Sie möglicherweise das Recht haben, den Inhalt und sogar das Verzeichnis zu löschen, können Sie möglicherweise nicht die ursprünglichen Eigentümer- und Modusbits im Verzeichnis zurücksetzen (z. B. sind Sie kein Superuser).
  4. Schließlich haben Sie etwas Geduld und lesen Sie den Code . Es ist lang und hässlich (in Sichtweite), hat sich aber als zuverlässig und effizient (in Gebrauch) erwiesen.

Hier ist eine lange und hässliche, aber zuverlässige und effiziente Lösung.

Es löst einige Probleme, die von den anderen Antwortenden nicht angesprochen werden:

  • Es behandelt symbolische Links korrekt, einschließlich des Nichtaufrufs shutil.rmtree()eines symbolischen Links (der den os.path.isdir()Test besteht, wenn er mit einem Verzeichnis verknüpft ist; auch das Ergebnis von os.walk()enthält symbolisch verknüpfte Verzeichnisse).
  • Es behandelt schreibgeschützte Dateien gut.

Hier ist der Code (die einzige nützliche Funktion ist clear_dir()):

import os
import stat
import shutil


# http://stackoverflow.com/questions/1889597/deleting-directory-in-python
def _remove_readonly(fn, path_, excinfo):
    # Handle read-only files and directories
    if fn is os.rmdir:
        os.chmod(path_, stat.S_IWRITE)
        os.rmdir(path_)
    elif fn is os.remove:
        os.lchmod(path_, stat.S_IWRITE)
        os.remove(path_)


def force_remove_file_or_symlink(path_):
    try:
        os.remove(path_)
    except OSError:
        os.lchmod(path_, stat.S_IWRITE)
        os.remove(path_)


# Code from shutil.rmtree()
def is_regular_dir(path_):
    try:
        mode = os.lstat(path_).st_mode
    except os.error:
        mode = 0
    return stat.S_ISDIR(mode)


def clear_dir(path_):
    if is_regular_dir(path_):
        # Given path is a directory, clear its content
        for name in os.listdir(path_):
            fullpath = os.path.join(path_, name)
            if is_regular_dir(fullpath):
                shutil.rmtree(fullpath, onerror=_remove_readonly)
            else:
                force_remove_file_or_symlink(fullpath)
    else:
        # Given path is a file or a symlink.
        # Raise an exception here to avoid accidentally clearing the content
        # of a symbolic linked directory.
        raise OSError("Cannot call clear_dir() on a symbolic link")

Ich verstehe nicht, in welchem ​​Kontext das Ändern des Dateimodus sinnvoll ist. Auf meinem Mac, os.remove, im Gegensatz zu dem rmProgramm ist, glücklich schreibgeschützte Dateien so lange zu löschen , wie Sie sie besitzen. Wenn es sich um eine Datei handelt, die Sie nicht besitzen und auf die Sie nur Lesezugriff haben, können Sie sie nicht löschen oder ihre Berechtigungen ändern. Ich kenne keine Situation auf einem System, auf dem Sie eine schreibgeschützte Datei nicht löschen os.removekönnen, ohne ihre Berechtigungen ändern zu können. Außerdem verwenden Sie lchmod, was weder auf meinem Mac noch unter Windows laut Dokumentation vorhanden ist. Für welche Plattform ist dieser Code gedacht?!
Mark Amery

14

Ich bin überrascht, dass niemand erwähnt hat, wie großartig pathlibes ist, diesen Job zu machen.

Wenn Sie nur Dateien in einem Verzeichnis entfernen möchten, kann dies ein Oneliner sein

from pathlib import Path

[f.unlink() for f in Path("/path/to/folder").glob("*") if f.is_file()] 

Um Verzeichnisse auch rekursiv zu entfernen, können Sie Folgendes schreiben:

from pathlib import Path
from shutil import rmtree

for path in Path("/path/to/folder").glob("**/*"):
    if path.is_file():
        path.unlink()
    elif path.is_dir():
        rmtree(path)

1
.iterdir()statt .glob(...)sollte auch funktionieren.
S. Kirby

12
import os
import shutil

# Gather directory contents
contents = [os.path.join(target_dir, i) for i in os.listdir(target_dir)]

# Iterate and remove each item in the appropriate manner
[os.remove(i) if os.path.isfile(i) or os.path.islink(i) else shutil.rmtree(i) for i in contents]

In einem früheren Kommentar wird auch die Verwendung von os.scandir in Python 3.5+ erwähnt. Zum Beispiel:

import os
import shutil

with os.scandir(target_dir) as entries:
    for entry in entries:
        if entry.is_file() or entry.is_symlink():
            os.remove(entry.path)
        elif entry.is_dir():
            shutil.rmtree(entry.path)

1
os.path.isdir()ist keine gültige Methode, um zwischen einem regulären Verzeichnis und einem symbolischen Link zu unterscheiden. Das Aufrufen shutil.rmtree()einer symbolischen Verbindung löst eine OSErrorAusnahme aus.
Rockallite

@ Rockallite Danke. Du hast recht. Ich habe das Beispiel aktualisiert.
Jacob Wan

8

Sie könnten besser dran sein os.walk() .

os.listdir()unterscheidet Dateien nicht von Verzeichnissen und Sie werden schnell in Schwierigkeiten geraten, wenn Sie versuchen, diese zu trennen. Es ist ein gutes Beispiel für die Verwendung os.walk()rekursiv ein Verzeichnis entfernen hier , und Hinweise, wie es um Ihre Gegebenheiten anzupassen.


6

Ich habe das Problem folgendermaßen gelöst:

import shutil
import os

shutil.rmtree(dirpath)
os.mkdir(dirpath)

7
Dies hat eine radikal andere Semantik als die Frage und sollte nicht als gültige Antwort angesehen werden.
Fatuhoku

1
In Bezug auf Respekt denke ich, dass "Löschen des Inhalts des lokalen Ordners" nicht das Entfernen des Ordners selbst beinhaltet. Gleiches Problem wie diese Antwort , nur dass man viele positive Stimmen bekommen hat!
Fatuhoku

3
Es ist wie die Beantwortung der Frage "Wie kann eine Funktion die Nummer 1 in Python zurückgeben?" mit def return_a_one (): launch_some_nukes () return 1
fatuhoku

2
Natürlich ist die Semantik anders: Aber Sie können es genauso gut als eine andere Sichtweise auf das Problem betrachten. Diese Lösung ist absolut gültig, da sie das Problem löst. Es gibt einen Unterschied zu Ihrem Beispiel 'launch_some_nukes': 1. Die Lösung ist kürzer und einfacher als die akzeptierte und im Gegensatz zu der von Ihnen angegebenen Antwort gültig. 2. In diesem Fall löscht und erstellt das Äquivalent 'launch_some_nukes' einen Ordner. Der Unterschied zwischen dem alten und dem neuen Ordner ist nur die Inode-Nummer (wahrscheinlich irrelevant für das OP)
ProfHase85

2
Es ist eher der Abriss des Wolkenkratzers und der Wiederaufbau eines genau der gleichen Größe;)
ProfHase85

5

Noch eine andere Lösung:

import sh
sh.rm(sh.glob('/path/to/folder/*'))

1
Beachten Sie, dass dies shnicht Teil der Standardbibliothek ist und von PyPI installiert werden muss, bevor Sie es verwenden können. Da dies tatsächlich rmin einem Unterprozess aufgerufen wird, funktioniert es auch nicht unter Windows, wo rmes nicht existiert. Es wird auch eine Ausnahme ausgelöst, wenn der Ordner Unterverzeichnisse enthält.
Mark Amery

5

Ich weiß, es ist ein alter Thread, aber ich habe etwas Interessantes von der offiziellen Seite von Python gefunden. Nur um eine andere Idee zum Entfernen aller Inhalte in einem Verzeichnis zu teilen. Weil ich bei der Verwendung von shutil.rmtree () einige Probleme mit der Autorisierung habe und das Verzeichnis nicht entfernen und neu erstellen möchte. Die ursprüngliche Adresse lautet http://docs.python.org/2/library/os.html#os.walk . Hoffe das könnte jemandem helfen.

def emptydir(top):
    if(top == '/' or top == "\\"): return
    else:
        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))

4

Gehen Sie einfach folgendermaßen vor, um alle Dateien im Verzeichnis sowie in den Unterverzeichnissen zu löschen, ohne die Ordner selbst zu entfernen:

import os
mypath = "my_folder" #Enter your path here
for root, dirs, files in os.walk(mypath):
    for file in files:
        os.remove(os.path.join(root, file))

3

Wenn Sie ein * nix-System verwenden, können Sie den Systembefehl nutzen.

import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)

3
Denn wie in der Frage angegeben, "Das aktuelle Projekt ist für Windows"
Sox mit Monica

3

Ziemlich intuitive Vorgehensweise:

import shutil, os


def remove_folder_contents(path):
    shutil.rmtree(path)
    os.makedirs(path)


remove_folder_contents('/path/to/folder')

3

Nun, ich denke dieser Code funktioniert. Der Ordner wird nicht gelöscht, und Sie können diesen Code verwenden, um Dateien mit der jeweiligen Erweiterung zu löschen.

import os
import glob

files = glob.glob(r'path/*')
for items in files:
    os.remove(items)

3

Ich musste Dateien aus 3 separaten Ordnern in einem einzigen übergeordneten Verzeichnis entfernen:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Dieser einfache Code hat den Trick für mich getan: (Ich bin unter Unix)

import os
import glob

folders = glob.glob('./path/to/parentdir/*')
for fo in folders:
  file = glob.glob(f'{fo}/*')
  for f in file:
    os.remove(f)

Hoffe das hilft.


1

Ich habe das Problem behoben, rmtree makedirsindem ich Folgendes hinzugefügt habe time.sleep():

if os.path.isdir(folder_location):
    shutil.rmtree(folder_location)

time.sleep(.5)

os.makedirs(folder_location, 0o777)

0

Antwort für eine begrenzte, spezifische Situation: Angenommen, Sie möchten die Dateien löschen, während Sie den Unterordnerbaum pflegen, können Sie einen rekursiven Algorithmus verwenden:

import os

def recursively_remove_files(f):
    if os.path.isfile(f):
        os.unlink(f)
    elif os.path.isdir(f):
        for fi in os.listdir(f):
            recursively_remove_files(os.path.join(f, fi))

recursively_remove_files(my_directory)

Vielleicht etwas abseits des Themas, aber ich denke, viele würden es nützlich finden


Die Verwendung os.walkauf die unter stackoverflow.com/a/54889532/1709587 gezeigte Weise ist möglicherweise eine bessere Möglichkeit, alle Dateien zu löschen, während die Verzeichnisstruktur intakt bleibt.
Mark Amery

-1

Angenommen temp_dir, gelöscht zu werden, wäre ein einzeiliger Befehl mit os:

_ = [os.remove(os.path.join(save_dir,i)) for i in os.listdir(temp_dir)]

Hinweis: Dies ist nur ein Einzeiler zum Löschen von Dateien. Löscht keine Verzeichnisse.

Hoffe das hilft. Vielen Dank.


-1

Verwenden Sie die folgende Methode, um den Inhalt eines Verzeichnisses zu entfernen, nicht das Verzeichnis selbst:

import os
import shutil

def remove_contents(path):
    for c in os.listdir(path):
        full_path = os.path.join(path, c)
        if os.path.isfile(full_path):
            os.remove(full_path)
        else:
            shutil.rmtree(full_path)

@ FabioSpaghetti Negativ
Amir Rezazadeh

danke Amir, ich suche nach einer Lösung, die einen bestimmten Ordner in allen Unterverzeichnissen eines Stammverzeichnisses findet und den Inhalt dieses Ordners entfernt
FabioSpaghetti

Dies fügt nichts Neues hinzu, das nicht bereits in den akzeptierten Antwortjahren gezeigt wurde, bevor Sie dies gepostet haben.
Mark Amery

-1

Der einfachste Weg, alle Dateien in einem Ordner zu löschen / alle Dateien zu entfernen

import os
files = os.listdir(yourFilePath)
for f in files:
    os.remove(yourFilePath + f)

Schlägt fehl, wenn Unterverzeichnisse vorhanden sind.
Mark Amery

-3

Dies sollte den Trick machen, indem Sie einfach das OS-Modul verwenden, um es aufzulisten und dann zu entfernen!

import os
DIR = os.list('Folder')
for i in range(len(DIR)):
    os.remove('Folder'+chr(92)+i)

Arbeitete für mich, irgendwelche Probleme lassen Sie mich wissen!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.