Comment supprimer le contenu d'un dossier?


470

Comment puis-je supprimer le contenu d'un dossier local en Python?

Le projet actuel est pour Windows, mais j'aimerais aussi voir * nix.


2
pour * nix pour être honnête, je voudrais simplement utiliseros.system('rm -rf folder')
Tilak Maddy

Réponses:


444
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
Si vous travaillez avec un très grand répertoire, et en particulier un répertoire réseau sous Windows, et que vous pouvez contrôler l'environnement dans lequel ce programme s'exécute, il pourrait être utile d'utiliser la fonction "os.scandir (dossier)" de Py3.5 au lieu de listdir. La syntaxe est assez différente après cela, mais assez simple à implémenter; heureux de l'afficher si d'autres le souhaitent.
Michael Scott Cuthbert

Je reçois un avertissement de pylint avec except Exception as e:qui lit W0703: Catching too general exception Exception. Existe-t-il une exception plus spécifique à intercepter ou dois-je l'ignorer?
John Hany

7
@JohnHany, je crois que vous voulez attraper OSError.
MikeB

246

Vous pouvez simplement faire ceci:

import os
import glob

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

Vous pouvez bien sûr utiliser un autre filtre dans votre chemin, par exemple: /YOU/PATH/*.txt pour supprimer tous les fichiers texte d'un répertoire.


12
@Blueicefield *ne listera pas les fichiers cachés, nous devrions également ajouterglob.glob('path/.*)
satoru

5
bien que pour supprimer la liste des fichiers, il me semble plus simple de faire:import sh; sh.rm(files)
Robin Winslow

2
Bien que import sh; sh.rm(files)cela semble plus joli, vous rencontrez des problèmes s'il y a plus de 1024 fichiers dans le répertoire.
Eugene

235

Vous pouvez supprimer le dossier lui-même, ainsi que tout son contenu, en utilisant shutil.rmtree:

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


Supprimer une arborescence de répertoires entière; chemin doit pointer vers un répertoire (mais pas un lien symbolique vers un répertoire). Si ignore_errors est vrai, les erreurs résultant d'échecs de suppression seront ignorées; si elles sont fausses ou omises, ces erreurs sont gérées en appelant un gestionnaire spécifié par onerror ou, si cela est omis, elles déclenchent une exception.


270
Cela supprimera non seulement le contenu mais aussi le dossier lui-même. Je ne pense pas que c'est ce que demande la question.
Iker Jimenez le

3
Je pense que c'est une bonne réponse. Pourquoi ne pas simplement supprimer le contenu et le dossier, puis refaire le dossier?
cssndrx

42
Parce que le nouveau répertoire et l'ancien ne seront plus les mêmes. Donc, si un programme est assis dans le répertoire, en attendant des choses, il aura le tapis retiré de dessous.
Mike Cooper

30
Recréez simplement le répertoire après rmtree. Commeos.makedirs(dir)
Iulius Curt

3
@IuliusCurt non, j'ai un répertoire monté dans le ram que je dois vider, et malheureusement je ne peux pas simplement le supprimer puis le recréer:OSError: [Errno 16] Device or resource busy
Arnaud P

80

En développant la réponse de mhawke, c'est ce que j'ai mis en œuvre. Il supprime tout le contenu d'un dossier mais pas le dossier lui-même. Testé sur Linux avec des fichiers, des dossiers et des liens symboliques, devrait également fonctionner sur Windows.

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
Pourquoi 'marcher' et pas seulement lister le contenu des dossiers?
Don

2
C'est la bonne réponse si vous souhaitez également supprimer des répertoires. walkest utilisé pour diviser les répertoires et les fichiers, qui doivent être traités différemment. Vous pouvez également utiliser os.listdir, mais vous devez vérifier si chaque entrée est un répertoire ou un fichier manuellement.
dkamins

7
C'est proche, mais os.walk et shutil.rmtree sont récursifs. os.walk n'est pas nécessaire car vous n'avez besoin que des fichiers et des répertoires de niveau supérieur à l'intérieur du répertoire à nettoyer. Utilisez simplement une instruction if sur les éléments dans os.listdir pour voir si chacun est un fichier ou un répertoire. Utilisez ensuite remove / unlink et rmtree respectivement.
Matthew Alpert du

1
@MatthewAlpert Notez cependant que os.walkcela ne récurrera pas ici, car il retourne un générateur qui ne regarde récursivement que les sous-répertoires lorsque vous essayez de le faire avancer, et au moment où vous avez fait votre première itération de cette boucle, il n'y a pas de sous-répertoires gauche pour regarder. En substance, os.walkest simplement utilisé ici comme moyen alternatif de distinguer les dossiers de niveau supérieur des fichiers de niveau supérieur; la récursivité n'est pas utilisée et nous ne payons aucun coût de performance pour cela. C'est excentrique, cependant, et je conviens que l'approche que vous proposez est meilleure simplement parce qu'elle est plus explicite et lisible.
Mark Amery

47

En utilisant rmtree et la recréation du dossier pourraient fonctionner, mais j'ai rencontré des erreurs lors de la suppression et de la recréation immédiate des dossiers sur les lecteurs réseau.

La solution proposée à l'aide de walk ne fonctionne pas car elle permet rmtreede supprimer des dossiers et peut ensuite tenter d'utiliser os.unlinksur les fichiers qui se trouvaient précédemment dans ces dossiers. Cela provoque une erreur.

Le posté glob solution tentera également de supprimer les dossiers non vides, provoquant des erreurs.

Je vous suggère d'utiliser:

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
Votre solution soulèvera également une erreur s'il existe un lien symbolique vers un autre répertoire.
Blueicefield

@Blueicefield - Pouvez-vous fournir un exemple. J'ai testé sous Linux en utilisant un fichier et un dossier avec lien symbolique, et je n'ai pas encore pu provoquer d'erreur.
jgoeders

@jgoeders - S'il y a un lien symbolique vers un répertoire, os.path.isfile()il reviendra False(car il suit les liens symboliques), et vous finirez par appeler shutil.rmtree()un lien symbolique, qui augmentera OSError("Cannot call rmtree on a symbolic link").
Rockallite

1
@Rockallite corrigé par chèque à islink
kevinf

1
Aussi: @kevinf est correct pour souligner la nécessité d'une islinkvérification ici pour gérer correctement les liens symboliques vers les répertoires. J'ai ajouté un tel chèque à la réponse acceptée.
Mark Amery

20

Cette:

  • supprime tous les liens symboliques
    • liens morts
    • liens vers des répertoires
    • liens vers des fichiers
  • supprime les sous-répertoires
  • ne supprime pas le répertoire parent

Code:

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

Comme beaucoup d'autres réponses, cela n'essaie pas d'ajuster les autorisations pour permettre la suppression des fichiers / répertoires.


15

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

Une solution plus robuste tenant également compte des fichiers et des répertoires serait (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
pour les opérations de grande envergure, l'utilisation du générateur peut être map( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
légèrement

essayant réellement d'utiliser cela, a réalisé que l'objet de la carte doit être itéré, donc un appel à la liste (ou quelque chose qui va itérer) est requis commelist(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
user25064

Le premier inclus dans la réponse, le second n'a aucun sens pour moi. Pourquoi devriez-vous itérer sur une fonction mappée sur un itérable? La carte fait ça.
fmonegaglia

1
En python3, vous devez envelopper mapdanslist de réellement itérer. Voir http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit du

Celui-ci ne fonctionnera certainement pas si 'mydir' contient au moins un dossier, car la dissociation ne fonctionne que pour les fichiers ...
kupsef

14

Remarques: si quelqu'un a voté contre ma réponse, j'ai quelque chose à expliquer ici.

  1. Tout le monde aime les réponses courtes et simples. Cependant, parfois la réalité n'est pas si simple.
  2. Revenons à ma réponse. Je sais que cela shutil.rmtree()pourrait être utilisé pour supprimer une arborescence de répertoires. Je l'ai utilisé plusieurs fois dans mes propres projets. Mais vous devez comprendre que le répertoire lui-même sera également supprimé parshutil.rmtree() . Bien que cela puisse être acceptable pour certains, ce n'est pas une réponse valide pour supprimer le contenu d'un dossier (sans effets secondaires) .
  3. Je vais vous montrer un exemple des effets secondaires. Supposons que vous ayez un répertoire avec des bits de propriétaire et de mode personnalisés , où il y a beaucoup de contenu. Ensuite, vous le supprimez avec shutil.rmtree()et le reconstruisez avec os.mkdir(). Et vous obtiendrez un répertoire vide avec le propriétaire par défaut (hérité) et les bits de mode à la place. Bien que vous ayez le privilège de supprimer le contenu et même le répertoire, vous ne pourrez peut-être pas redéfinir le propriétaire d'origine et les bits de mode sur le répertoire (par exemple, vous n'êtes pas un superutilisateur).
  4. Enfin, soyez patient et lisez le code . Il est long et moche (en vue), mais s'est avéré fiable et efficace (en cours d'utilisation).

Voici une solution longue et moche, mais fiable et efficace.

Il résout quelques problèmes qui ne sont pas traités par les autres répondeurs:

  • Il gère correctement les liens symboliques, y compris ne pas faire appel shutil.rmtree()à un lien symbolique (qui réussira le os.path.isdir()test s'il établit un lien vers un répertoire; même le résultat de os.walk()contient également des répertoires liés symboliques).
  • Il gère bien les fichiers en lecture seule.

Voici le code (la seule fonction utile est 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")

Je ne comprends pas dans quel contexte changer le mode de fichier est logique. Sur mon Mac, os.remove, contrairement à l' rmutilitaire, est heureux de supprimer des fichiers en lecture seule aussi longtemps que vous les possédez. En attendant, si c'est un fichier que vous ne possédez pas et auquel vous avez uniquement accès en lecture seule, vous ne pouvez pas le supprimer ou modifier ses autorisations. Je ne connais aucune situation sur aucun système où vous ne seriez pas en mesure de supprimer un fichier en lecture seule avec os.removeencore être en mesure de modifier ses autorisations. De plus, vous utilisez lchmod, qui n'existe pas sur mon Mac, ni sur Windows selon ses documents. À quelle plateforme ce code est-il destiné?!
Mark Amery

14

Je suis surpris que personne n'ait mentionné le formidable pathlibde faire ce travail.

Si vous souhaitez uniquement supprimer des fichiers dans un répertoire, il peut s'agir d'un oneliner

from pathlib import Path

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

Pour supprimer également récursivement des répertoires, vous pouvez écrire quelque chose comme ceci:

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()au lieu de .glob(...)devrait également fonctionner.
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]

Un commentaire précédent mentionne également l'utilisation d'os.scandir dans Python 3.5+. Par exemple:

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()n'est pas un moyen valide de faire la distinction entre un répertoire normal et un lien symbolique. Faire appel shutil.rmtree()à un lien symbolique déclenchera une OSErrorexception.
Rockallite

@Rockallite Merci. Tu as raison. J'ai mis à jour l'exemple.
Jacob Wan

8

Vous feriez peut-être mieux de l'utiliser os.walk()pour cela.

os.listdir()ne distingue pas les fichiers des répertoires et vous aurez rapidement des problèmes pour les dissocier. Il existe un bon exemple d'utilisation os.walk()pour supprimer récursivement un répertoire ici , et des conseils sur la façon de l'adapter à votre situation.


6

J'avais l'habitude de résoudre le problème de cette façon:

import shutil
import os

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

7
Cela a une sémantique radicalement différente de celle de la question et ne doit pas être considérée comme une réponse valide.
fatuhoku

1
Avec égards, je pense que "Supprimer le contenu du dossier local" n'implique pas de supprimer le dossier lui-même. Même problème que cette réponse , sauf que l'on a eu beaucoup de votes positifs!
fatuhoku

3
C'est comme répondre à la question "Comment puis-je avoir une fonction renvoyer le numéro 1 en Python?" avec def return_a_one (): launch_some_nukes () return 1
fatuhoku

2
Bien sûr, la sémantique est différente: mais vous pourriez aussi bien la considérer comme une autre façon de voir le problème. Cette solution est parfaitement valable car elle résout le problème. Il y a une différence avec votre exemple 'launch_some_nukes': 1. La solution est plus courte et plus facile que celle acceptée et contrairement à la réponse que vous avez citée, elle est valide. 2. l'équivalent 'launch_some_nukes' dans ce cas est la suppression et la recréation d'un dossier. La différence entre l'ancien et le nouveau dossier n'est que le numéro d'inode (probablement non pertinent pour l'OP)
ProfHase85

2
Il s'agit plutôt de démolir le gratte-ciel et d'en reconstruire un exactement de la même taille;)
ProfHase85

5

Encore une autre solution:

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

1
Notez que cela shne fait pas partie de la bibliothèque standard et doit être installé à partir de PyPI avant de pouvoir l'utiliser. De plus, puisque cela invoque réellement rmdans un sous-processus, cela ne fonctionnera pas sur Windows où il rmn'existe pas. Il lèvera également une exception si le dossier contient des sous-répertoires.
Mark Amery

5

Je sais que c'est un vieux fil mais j'ai trouvé quelque chose d'intéressant sur le site officiel de python. Juste pour partager une autre idée de suppression de tout le contenu d'un répertoire. Parce que j'ai des problèmes d'autorisation lors de l'utilisation de shutil.rmtree () et je ne veux pas supprimer le répertoire et le recréer. L'adresse d'origine est http://docs.python.org/2/library/os.html#os.walk . J'espère que cela pourrait aider quelqu'un.

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

Pour supprimer tous les fichiers du répertoire ainsi que ses sous-répertoires, sans supprimer les dossiers eux-mêmes, il suffit de procéder comme suit:

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

Si vous utilisez un système * nix, pourquoi ne pas utiliser la commande système?

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

3
Parce que, comme indiqué dans la question, "Le projet actuel est pour Windows"
sox avec Monica

3

Façon assez intuitive de le faire:

import shutil, os


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


remove_folder_contents('/path/to/folder')

3

Eh bien, je pense que ce code fonctionne. Il ne supprimera pas le dossier et vous pouvez utiliser ce code pour supprimer les fichiers ayant l'extension particulière.

import os
import glob

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

3

J'ai dû supprimer des fichiers de 3 dossiers séparés dans un seul répertoire parent:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Ce code simple a fait l'affaire pour moi: (je suis sous 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)

J'espère que cela t'aides.


1

J'ai résolu le problème avec rmtree makedirsen ajoutant time.sleep()entre:

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

time.sleep(.5)

os.makedirs(folder_location, 0o777)

0

Répondez à une situation limitée et spécifique: en supposant que vous souhaitez supprimer les fichiers tout en conservant l'arborescence des sous-dossiers, vous pouvez utiliser un algorithme récursif:

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)

Peut-être légèrement hors sujet, mais je pense que beaucoup le trouveraient utile


L'utilisation os.walkde la manière indiquée sur stackoverflow.com/a/54889532/1709587 est peut-être une meilleure façon de supprimer tous les fichiers tout en laissant la structure du répertoire intacte.
Mark Amery

-1

En supposant temp_dirqu'elle soit supprimée, une commande sur une seule ligne utilisant osserait:

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

Remarque: Il s'agit uniquement d'une ligne pour la suppression de fichiers 'Ne supprime pas les répertoires.

J'espère que cela t'aides. Merci.


-1

Utilisez la méthode ci-dessous pour supprimer le contenu d'un répertoire, pas le répertoire lui-même:

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 Negative
Amir Rezazadeh

merci Amir, je cherche une solution qui trouve un certain dossier dans tous les sous-répertoires d'un répertoire racine et supprime le contenu de ce dossier
FabioSpaghetti

Cela n'ajoute rien de nouveau qui n'était pas déjà affiché dans les années de réponse acceptées avant que vous ne postiez cela.
Mark Amery

-1

la façon la plus simple de supprimer tous les fichiers d'un dossier / supprimer tous les fichiers

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

Échoue s'il existe des sous-répertoires.
Mark Amery

-3

Cela devrait faire l'affaire en utilisant simplement le module OS pour lister puis supprimer!

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

A travaillé pour moi, tous les problèmes me le font savoir!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.