¿Cómo eliminar el contenido de una carpeta?

470

¿Cómo puedo eliminar el contenido de una carpeta local en Python?

El proyecto actual es para Windows, pero me gustaría ver * nix también.

UnkwnTech
fuente
2
para * nix para ser honesto, solo usaríaos.system('rm -rf folder')
Tilak Maddy

Respuestas:

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))
Nick Stinemates
fuente
44
Si está trabajando con un directorio muy grande, y particularmente un directorio de red en Windows, y puede controlar el entorno en el que se ejecuta este programa, puede valer la pena utilizar la función "os.scandir (carpeta)" de Py3.5 en lugar de listdir La sintaxis es bastante diferente después de eso, pero es bastante simple de implementar; feliz de publicarlo si otros quieren.
Michael Scott Cuthbert
Recibo una advertencia de pylint con except Exception as e:esas lecturas W0703: Catching too general exception Exception. ¿Hay una excepción más específica para atrapar o debería ignorarla?
John Hany
77
@ JohnHany, creo que quieres atrapar OSError.
MikeB
246

Simplemente puedes hacer esto:

import os
import glob

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

Por supuesto, puede usar otro filtro en su ruta, por ejemplo: /YOU/PATH/*.txt para eliminar todos los archivos de texto en un directorio.

Blueicefield
fuente
12
@Blueicefield *no oculta la lista de archivos, se debe añadir tambiénglob.glob('path/.*)
Satoru
55
aunque para borrar la lista de archivos, parece más sencillo para mí hacer:import sh; sh.rm(files)
Robin Winslow
2
Si bien import sh; sh.rm(files)parece más bonito, tiene problemas si hay más de 1024 archivos en el directorio.
Eugene
235

Puede eliminar la carpeta en sí, así como todo su contenido, usando shutil.rmtree:

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


Eliminar un árbol de directorios completo; la ruta debe apuntar a un directorio (pero no a un enlace simbólico a un directorio). Si ignore_errors es verdadero, los errores resultantes de eliminaciones fallidas serán ignorados; si es falso u omitido, dichos errores se manejan llamando a un controlador especificado por onerror o, si se omite, generan una excepción.

Oli
fuente
270
Esto no solo eliminará el contenido sino también la carpeta en sí. No creo que sea lo que hace la pregunta.
Iker Jimenez
3
Creo que es una buena respuesta. ¿Por qué no eliminas el contenido y la carpeta y luego vuelves a hacer la carpeta?
cssndrx
42
Porque el nuevo directorio y el antiguo no serán los mismos. Entonces, si un programa está sentado en el directorio, esperando cosas, se quitará la alfombra debajo de él.
Mike Cooper el
30
Simplemente recrea el directorio después rmtree. Me gustaos.makedirs(dir)
Iulius Curt
3
@IuliusCurt no, tengo un directorio montado en RAM que necesito vaciar, y desafortunadamente no puedo simplemente borrarlo y luego volver a crearlo:OSError: [Errno 16] Device or resource busy
Arnaud P
80

Ampliando la respuesta de mhawke, esto es lo que he implementado. Elimina todo el contenido de una carpeta pero no la carpeta en sí. Probado en Linux con archivos, carpetas y enlaces simbólicos, también debería funcionar en 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))
Iker Jiménez
fuente
1
¿Por qué 'caminar' y no solo listar el contenido de la carpeta?
Don
2
Esta es la respuesta correcta si desea eliminar directorios también. walkse usa para dividir directorios frente a archivos, que deben manejarse de manera diferente. También podría usar os.listdir, pero tendría que verificar si cada entrada es un directorio o archivo de forma manual.
dkamins
77
Esto está cerca, pero tanto os.walk como shutil.rmtree son recursivos. os.walk es innecesario ya que solo necesita limpiar los archivos y directorios en el nivel superior dentro del directorio. Simplemente use una declaración if en elementos en os.listdir para ver si cada uno es un archivo o directorio. Luego use remove / unlink y rmtree respectivamente.
Matthew Alpert
1
@MatthewAlpert Note, sin embargo, eso os.walkno se repetirá aquí, porque devuelve un generador que solo mira recursivamente los subdirectorios cuando intentas avanzarlo, y para cuando hayas realizado tu primera iteración de este ciclo, no hay subdirectorios a la izquierda para mirar. En esencia, os.walksolo se está utilizando aquí como una forma alternativa de distinguir las carpetas de nivel superior de los archivos de nivel superior; la recursividad no se está utilizando y no pagamos ningún costo de rendimiento por ello. Sin embargo, es excéntrico, y estoy de acuerdo en que el enfoque que sugiere es mejor simplemente porque es más explícito y legible.
Mark Amery el
47

Utilizando rmtree y la recreación de la carpeta podrían funcionar, pero me he encontrado con errores al eliminar y volver a crear carpetas de inmediato en las unidades de red.

La solución propuesta usando walk no funciona como lo hace rmtreepara eliminar carpetas y luego puede intentar usar os.unlinken los archivos que estaban previamente en esas carpetas. Esto causa un error.

El publicado glob solución también intentará eliminar carpetas no vacías, lo que provocará errores.

Te sugiero que uses:

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)
jgoeders
fuente
1
Su solución también generará un error si hay un enlace simbólico a otro directorio.
Blueicefield
@Blueicefield - ¿Puedes dar un ejemplo? He probado en Linux usando un archivo y una carpeta con enlace simbólico, y todavía no he podido causar un error.
jgoeders
@jgoeders: si hay un enlace simbólico a un directorio, os.path.isfile()volverá False(porque sigue enlaces simbólicos), y terminará llamando shutil.rmtree()a un enlace simbólico, que aumentará OSError("Cannot call rmtree on a symbolic link").
Rockallite
1
@Rockallite corregido por cheque a islink
kevinf
1
Además: @kevinf es correcto al señalar la necesidad de una islinkverificación aquí para manejar enlaces simbólicos a directorios correctamente. Agregué tal verificación a la respuesta aceptada.
Mark Amery el
20

Esta:

  • elimina todos los enlaces simbólicos
    • enlaces muertos
    • enlaces a directorios
    • enlaces a archivos
  • elimina subdirectorios
  • no elimina el directorio padre

Código:

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

Como muchas otras respuestas, esto no intenta ajustar los permisos para permitir la eliminación de archivos / directorios.

Jon Chu
fuente
15

Como un 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)) ) )

Una solución más sólida para los archivos y directorios también sería (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)) )
fmonegaglia
fuente
1
para operaciones grandes, usar el generador puede ser fraccionalmente más eficientemap( os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir)) )
user25064
En realidad, tratando de usar esto, me di cuenta de que el objeto del mapa debe list(map(os.unlink, (os.path.join( mydir,f) for f in os.listdir(mydir))))
repetirse para que
El primero incluido en la respuesta, el segundo no tiene sentido para mí. ¿Por qué debería iterar sobre una función asignada a un iterable? El mapa hace eso.
fmonegaglia
1
En python3, hay que envolver mapen list que en realidad iterate. Ver http://stackoverflow.com/questions/1303347/getting-a-map-to-return-a-list-in-python-3-x
paulwasit
Definitivamente, este no funcionará si 'mydir' contiene al menos una carpeta, ya que unlink funciona solo para archivos ...
kupsef
14

Notas: en caso de que alguien rechace mi respuesta, tengo algo que explicar aquí.

  1. A todos les gustan las respuestas cortas y simples. Sin embargo, a veces la realidad no es tan simple.
  2. De vuelta a mi respuesta. Sé que shutil.rmtree()podría usarse para eliminar un árbol de directorios. Lo he usado muchas veces en mis propios proyectos. Pero debe darse cuenta de que el directorio en sí también será eliminado porshutil.rmtree() . Si bien esto puede ser aceptable para algunos, no es una respuesta válida para eliminar el contenido de una carpeta (sin efectos secundarios) .
  3. Te mostraré un ejemplo de los efectos secundarios. Suponga que tiene un directorio con propietario personalizado y bits de modo, donde hay muchos contenidos. Luego lo eliminas shutil.rmtree()y lo reconstruyes con os.mkdir(). Y obtendrás un directorio vacío con el predeterminado propietario (heredado) y bits de modo en su lugar. Si bien es posible que tenga el privilegio de eliminar el contenido e incluso el directorio, es posible que no pueda restablecer el propietario original y los bits de modo en el directorio (por ejemplo, no es un superusuario).
  4. Finalmente, sea ​​paciente y lea el código . Es largo y feo (a la vista), pero ha demostrado ser confiable y eficiente (en uso).

Aquí hay una solución larga y fea, pero confiable y eficiente.

Resuelve algunos problemas que los otros respondedores no abordan:

  • Maneja correctamente los enlaces simbólicos, incluida la no invocación shutil.rmtree()de un enlace simbólico (que pasará la os.path.isdir()prueba si se vincula a un directorio; incluso el resultado de os.walk()contiene también directorios simbólicos vinculados).
  • Maneja bien los archivos de solo lectura.

Aquí está el código (la única función útil es 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")
Rockallita
fuente
No entiendo en qué contexto tiene sentido cambiar el modo de archivo. En mi Mac, os.remove, a diferencia de la rmutilidad, es feliz para borrar archivos de sólo lectura, siempre y cuando sea el propietario. Mientras tanto, si es un archivo que no es de su propiedad al que solo tiene acceso de solo lectura, entonces no puede eliminarlo ni cambiar sus permisos. No conozco ninguna situación en ningún sistema en el que no pueda eliminar un archivo de solo lectura y os.removeaún así pueda cambiar sus permisos. Además, utiliza lchmod, que no existe en mi Mac, ni en Windows de acuerdo con sus documentos. ¿Para qué plataforma es este código?
Mark Amery el
14

Me sorprende que nadie haya mencionado lo increíble pathlibque es hacer este trabajo.

Si solo desea eliminar archivos de un directorio, puede ser un elemento de línea

from pathlib import Path

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

Para eliminar también directorios de forma recursiva, puede escribir algo como esto:

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)
Fornido
fuente
1
.iterdir()en lugar de .glob(...)también debería funcionar.
S. Kirby el
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 comentario anterior también menciona el uso de os.scandir en Python 3.5+. Por ejemplo:

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)
Jacob Wan
fuente
1
os.path.isdir()no es una forma válida de distinguir entre un directorio regular y un enlace simbólico. Llamar shutil.rmtree()a un enlace simbólico generará una OSErrorexcepción.
Rockallite
@Rockallite Gracias. Tienes razón. Actualicé el ejemplo.
Jacob Wan
8

Puede que sea mejor usarlo os.walk()para esto.

os.listdir()no distingue los archivos de los directorios y rápidamente tendrás problemas para desvincularlos. Hay un buen ejemplo del uso os.walk()para eliminar de forma recursiva un directorio aquí , y consejos sobre cómo adaptarlo a sus circunstancias.

mhawke
fuente
6

Solía ​​resolver el problema de esta manera:

import shutil
import os

shutil.rmtree(dirpath)
os.mkdir(dirpath)
ProfHase85
fuente
77
Esto tiene una semántica radicalmente diferente de lo que hace la pregunta y no debe considerarse como una respuesta válida.
fatuhoku
1
Con respecto, creo que "Eliminar el contenido de la carpeta local" no implica eliminar la carpeta en sí. El mismo problema que esta respuesta , ¡excepto que se obtuvieron muchos votos a favor!
fatuhoku
3
Es como responder la pregunta "¿Cómo hago que una función devuelva el número 1 en Python?" with def return_a_one (): launch_some_nukes () return 1
fatuhoku
2
Por supuesto, la semántica es diferente: pero bien podría considerarlo como otra forma de ver el problema. Esta solución es perfectamente válida ya que resuelve el problema. Hay una diferencia en su ejemplo de 'launch_some_nukes': 1. La solución es más corta y más fácil que la aceptada y, en oposición a la respuesta que citó, es válida. 2. El equivalente de 'launch_some_nukes' en este caso es eliminar y volver a crear una carpeta. La diferencia entre la carpeta antigua y la nueva es solo el número de inodo (probablemente irrelevante para el OP)
ProfHase85
2
Es más bien demoler el rascacielos y reconstruir uno exactamente del mismo tamaño;)
ProfHase85
5

Otra solución más:

import sh
sh.rm(sh.glob('/path/to/folder/*'))
Robin Winslow
fuente
1
Tenga en cuenta que shno es parte de la biblioteca estándar y necesita instalarse desde PyPI antes de poder usarla. Además, dado que esto realmente se invoca rmen un subproceso, no funcionará en Windows donde rmno existe. También generará una excepción si la carpeta contiene subdirectorios.
Mark Amery el
5

Sé que es un hilo viejo, pero he encontrado algo interesante en el sitio oficial de Python. Solo por compartir otra idea para eliminar todo el contenido de un directorio. Porque tengo algunos problemas de autorización cuando uso shutil.rmtree () y no quiero eliminar el directorio y volver a crearlo. La dirección original es http://docs.python.org/2/library/os.html#os.walk . Espero que pueda ayudar a alguien.

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))
Aserrador
fuente
4

Para eliminar todos los archivos dentro del directorio, así como sus subdirectorios, sin eliminar las carpetas, simplemente haga esto:

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))
Kevin Patel
fuente
3

Si está utilizando un sistema * nix, ¿por qué no aprovechar el comando del sistema?

import os
path = 'folder/to/clean'
os.system('rm -rf %s/*' % path)
silverbullettt
fuente
3
Porque, como se indicó en la pregunta, "El proyecto actual es para Windows"
sox con Monica
3

Manera bastante intuitiva de hacerlo:

import shutil, os


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


remove_folder_contents('/path/to/folder')
Manrique
fuente
3

Bueno, creo que este código está funcionando. No eliminará la carpeta y puede usar este código para eliminar archivos que tengan la extensión particular.

import os
import glob

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

Tuve que eliminar archivos de 3 carpetas separadas dentro de un solo directorio principal:

directory
   folderA
      file1
   folderB
      file2
   folderC
      file3

Este código simple hizo el truco para mí: (Estoy en 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)

Espero que esto ayude.

NicoBar
fuente
1

Resolví el problema rmtree makedirsagregando time.sleep()entre:

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

time.sleep(.5)

os.makedirs(folder_location, 0o777)
fisica
fuente
0

Responda a una situación limitada y específica: suponiendo que desea eliminar los archivos mientras mantiene el árbol de subcarpetas, puede usar un algoritmo recursivo:

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)

Tal vez un poco fuera de tema, pero creo que muchos lo encontrarían útil

fmonegaglia
fuente
Usar os.walkde la manera que se muestra en stackoverflow.com/a/54889532/1709587 es quizás una mejor manera de eliminar todos los archivos y dejar intacta la estructura del directorio.
Mark Amery el
-1

Suponiendo temp_dirque se elimine, un comando de una sola línea usando ossería:

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

Nota: Esto es solo una línea para eliminar archivos 'No elimina directorios.

Espero que esto ayude. Gracias.

Fin-2-Fin
fuente
-1

Use el siguiente método para eliminar el contenido de un directorio, no el directorio en sí:

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)
Amir Rezazadeh
fuente
@FabioSpaghetti Negative
Amir Rezazadeh
gracias Amir, estoy buscando una solución que encuentre una carpeta determinada en todos los subdirectorios de un directorio raíz y elimine el contenido de esa carpeta
FabioSpaghetti
Esto no agrega nada nuevo que no se haya mostrado en la respuesta aceptada años antes de publicar esto.
Mark Amery el
-1

La forma más fácil de eliminar todos los archivos en una carpeta / eliminar todos los archivos

import os
files = os.listdir(yourFilePath)
for f in files:
    os.remove(yourFilePath + f)
PyBoss
fuente
Falla si hay subdirectorios.
Mark Amery el
-3

¡Esto debería hacer el truco simplemente usando el módulo del sistema operativo para enumerar y luego eliminar!

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

Funcionó para mí, cualquier problema házmelo saber!

B. Archivador
fuente